Markdown no estaba acostumbrado a esto por primera vez, y tomó mucho tiempo. . . . . .
Corte de papel llameante
度度熊有一张纸条和一把剪刀。
纸条上依次写着 N 个数字,数字只可能是 0 或者 1。
度度熊想在纸条上剪 K 刀(每一刀只能剪在数字和数字之间),这样就形成了 K+1 段。
他再把这 K+1 段按一定的顺序重新拼起来。
不同的剪和接的方案,可能会得到不同的结果。
度度熊好奇的是,前缀 1 的数量最多能是多少。
De entrada
有多组数据,读到EOF结束。
对于每一组数据,第一行读入两个数 N 和 K 。
第二行有一个长度为 N 的字符串,依次表示初始时纸条上的 N 个数。
0≤K<N≤10000
所有数据 N 的总和不超过100000
Salida
对于每一组数据,输出一个数,表示可能的最大前缀 1 的数量。
Muestra
De entrada
5 1
11010
5 2
11010
Salida
2 3
#include <iostream> #include <cstring> #include <algorithm> usando el espacio de nombres std; int num [ 100005 ]; int cmp ( int a, int b) { return a> b; } int main () { int n, k; while (scanf ( " % d% d " , & n, & k) == 2 ) { string s; cin >> s; int all = 0 , i; // 所有 的 1 para (i = 0 ; i <n; i ++) if (s [i] == ' 1 ' ) all ++ ; int pre = 0 ; // front 'contínuo 1' para (i = 0 ; i <n; i ++ ) { if (s [i] == ' 1 ' ) pre ++ ; else break ; } int left1 = 0 ; // detrás de 'contínuo 1' if (pre! = all) { // tenga en cuenta que la posible cadena s es todo 1 para (i = n- 1 ; i> = 0 ; i-- ) { if (s [i] == '1 ' ) left1 ++ ; else break ; } } memset (num, 0 , sizeof (num)); int j = 0 , flag; // j: indica el número de' continuo 1 'en el medio para (i = pre; i < n-left1; i ++) { // almacena el medio 'continuo 1', usa num [] para almacenar flag = 0 ; while (s [i] == ' 1 ' && i < n) { num [j] ++ ; i ++ ; flag =1 ; } if (flag) j ++ ; } sort (num, num + j, cmp); // El 'continuo 1' del medio se ordena de grande a pequeño int sum = 0 , cur = k; // cur: indica la corriente El número restante de cuchillos // comienza la estrategia codiciosa, primero trata con el medio, presta atención a dejar dos cuchillos, porque el primero y el último solo se pueden reducir en un cuchillo para (i = 0 ; i <j && cur> 2 ; i ++) { // El 'continuo 1' en el medio, debes cortar con dos cuchillos suma + = num [i]; num [i] = 0 ; // Eliminar cur- = 2 ; } // Juzgar los dos últimos cuchillos para (i = 0 ; i <j; i ++) if (num [i]! = 0 ) break ; // encuentra el 'continuo 1' más grande si no se corta en el medio (cur> = 2 ) { // Si el número restante de cuchillos> = 2, son los dos más grandes de num [i], pre, left1 y los tres (razón: demuéstralo en el borrador) si (pre <= left1 && pre <= NUM [I]) Suma + = (left1 + NUM [I]); el otro IF (left1 <= pre && left1 <= NUM [I]) Suma + = (pre + NUM [I]); el otro SUM + = ( left1 + pre); } else if (cur == 1 ) { // El número restante de cuchillos == 1, es decir k == 3, dos casos: 1. cortar el centro, 2. cortar la cola (tenga en cuenta que si se corta la cola, el primer 1 también se puede conectar) sum + = max (num [i], pre + left1); } if (k == 0 ) printf ( " % d \ n " , pre); // k == 0, que es el primer "continuo 1 " sino printf ( " % d \ n " , sum); } return 0 ; }