燃える紙カット

Markdownは初めてそれに慣れず、長い時間がかかりました。

燃える紙カット

度度熊有一张纸条和一把剪刀。

纸条上依次写着 N 个数字,数字只可能是 0 或者 1。

度度熊想在纸条上剪 K 刀(每一刀只能剪在数字和数字之间),这样就形成了 K+1 段。

他再把这 K+1 段按一定的顺序重新拼起来。

不同的剪和接的方案,可能会得到不同的结果。

度度熊好奇的是,前缀 1 的数量最多能是多少。

入力

有多组数据,读到EOF结束。

对于每一组数据,第一行读入两个数 N 和 K 。

第二行有一个长度为 N 的字符串,依次表示初始时纸条上的 N 个数。

0≤K<N≤10000

所有数据 N 的总和不超过100000

アウトプット

对于每一组数据,输出一个数,表示可能的最大前缀 1 的数量。

サンプル

入力

5 1
11010
5 2
11010

アウトプット

2
3



#include <iostream>

#include <cstring>

#include <アルゴリズム>

 名前空間std を使用します

 

int num [ 100005 ];

int cmp(int a、int b){

    a> bを返す;

}

int main(){

    int n、k;

    while(scanf(" %d%d "、&​​n、&k)== 2 ){

        文字列s;

        cin >> s;

        int all = 0、i;   // すべて1

        for(i = 0 ; i <n; i ++)     if(s [i] == ' 1 ')all ++ ;

 

        int pre = 0 ;     // 先行する「連続1」

        for(i = 0 ; i <n; i ++ ){

            if(s [i] == ' 1 ')pre ++ ;

            さもなければ  壊れる;

        }

        int left1 = 0 ;   // 'continuous 1'の後ろ

 

        if(pre!= all){ // 可能な文字列sはすべて1であることに注意してください

            for(i = n- 1 ; i> = 0 ; i -- ){

                if(s [i] == ' 1 ')left1 ++ ;

                さもなければ  壊れる;

            }

        }

        memset(num、0sizeof (num));

        int j = 0、flag;                   // j:途中の「連続1」の数を示します

        for(i = pre; i <n-left1; i ++){    // 中央の「連続1」を格納し、num []を使用して

            flag = 0 を格納します。

            while(s [i] == ' 1 ' && i < n){

                num [j] ++ ;

                i ++ ;

                フラグ = 1 ;

            }

            if(フラグ)j ++ ;        

        }

        sort(num、num + j、cmp);         // 中央の「連続1」は、最大から最小にソートされます

        int sum = 0、cur = k;             // cur:現在残っているナイフの数を示します

        

        // 貪欲な戦略を開始し、最初に真ん中に対処し、2つのナイフを残すように注意します。最初と最後のナイフは1つだけ削減できるためです

        for(i = 0 ; i <j && cur> 2 ; i ++){   // 中間の「連続1」では、2つのナイフを使用して

            合計 + = num [i]; をカットする必要があります。

            num [i] = 0 ;                 // 使用後、
            cur- = 2を削除
;

        }

        

        // 残りの最後の2つのナイフを判断する

        for(i = 0 ; i <j; i ++)   if(num [i]!= 0break ;    // 途中でカットされていない最大の「連続1」を見つける

        if(cur> = 2){                                // 残りのナイフ数> = 2の場合、num [i]、pre、left1、および3つの最大の2つです(理由:ドラフトで説明してください)

            if(pre <= left1 && pre <= num [i])sum + =(left1 + num [i]);

            else  if(left1 <= pre && left1 <= num [i])sum + =(pre + num [i]);

            それ以外の場合   sum + =(left1 + pre);

        } else  if(cur == 1){                         // ナイフ
残りの数== 1、つまりk == 3、2つの場合:1.中央をカットする、2。尾をカットする(尾をカットする場合、最初の1接続できる)
            sum + = max(num [i]、pre + left1);

        }

        if(k == 0)printf(" %d \ n "、pre);               // k == 0、これはヘッダーの「連続1」です

        それ以外の場合、   printf(" %d \ n " 、sum);

    }

     0を返します

}

 

おすすめ

転載: www.cnblogs.com/LightyaChoo/p/12716561.html