Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2508 Accepted Submission(s): 470
度度熊有一张纸条和一把剪刀。
纸条上依次写着 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
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6376
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int cmp(int a,int b)
{
return a>b;
}
char s[100005];
int a[100005];
int n,k;
int main()
{
while(cin>>n>>k)
{
cin>>s;
int i;
int head=0,tail=0,all=0;
for( i=0;i<n;i++)
if(s[i]==‘1‘) all++; // 记录所有 1 的个数
for( i=0;i<n;i++)
if(s[i]==‘1‘) head++;
else break; // 开头 1 的个数
if(head!=all) // 注意可能所有的数都是 1
{
for( i=n-1;i>=0;i--)
if(s[i]==‘1‘) tail++;
else break;
}
memset(a,0,sizeof(a));
int j=0,flag;
for( i=head;i<n-tail;i++)
{
flag=0;
while(s[i]==‘1‘ && i<n)
{
a[j]++; //将每一段的 1 的个数记录到数组a中 (头尾的 1 不计入)
i++;
flag=1;
}
if(flag) j++;
}
sort(a,a+j,cmp); //a从大到小排序
int sum=0;
int cur=k;
for( i=0; i<j && cur>2 ;i++) //先处理中间部分,中间的 1 每剪一次要两刀
{
sum+=a[i];
cur-=2;
}
if(cur>=2) // 要大于等于 2 ,如果是cur==2 ,全是 1 的情况会输出 0 导致错误
{
sum+=max(head+tail,max(head+a[i],tail+a[i]));
}
else if(cur==1) // 若剪下尾部的1 可以连到开头上
{
sum+=max(a[i],head+tail);
}
if(k==0) cout<<head<<endl;
else cout<<sum<<endl;
}
return 0;
}
原文:https://www.cnblogs.com/lkfsblogs/p/12634368.html