题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=825&pid=1003
题目如下:
1003任何时候的纸条(最初的纸条或者剪下来后的部分)都不能前后翻转
度度熊剪纸条
Accepts: 488 Submissions: 5471
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
度度熊有一张纸条和一把剪刀。
纸条上依次写着 NN 个数字,数字只可能是 00 或者 11。
度度熊想在纸条上剪 KK 刀(每一刀只能剪在数字和数字之间),这样就形成了 K+1K+1 段。
他再把这 K+1K+1 段按一定的顺序重新拼起来。
不同的剪和接的方案,可能会得到不同的结果。
度度熊好奇的是,前缀 11 的数量最多能是多少。
Input
有多组数据,读到EOF结束。
对于每一组数据,第一行读入两个数 NN 和 KK 。
第二行有一个长度为 NN 的字符串,依次表示初始时纸条上的 NN 个数。
0 \leq K < N \leq 100000≤K<N≤10000
所有数据 NN 的总和不超过100000100000
Output
对于每一组数据,输出一个数,表示可能的最大前缀 11 的数量。
Sample Input
5 1
11010
5 2
11010
Sample Output
2
3
这个题目,用贪心方法来做,想想怎样才能剪得1最多?
注意两点:1. 先处理中间的”连续的1“
2. 一定要留下两刀出来,再判断剪(首,尾,还是中间)怎么才划算?
详情见代码注释:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace 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
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++;
else break;
}
int left1=0; //后面‘连续的1’
if(pre!=all) {//注意可能字符串s全为1
for(i=n-1; i>=0; i--) {
if(s[i]=='1') left1++;
else break;
}
}
memset(num,0,sizeof(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++;
flag=1;
}
if(flag) j++;
}
sort(num,num+j,cmp); //中间的‘连续的1’从大到小排序
int sum=0,cur=k; //cur:表示当前剩下的刀数
//开始贪心策略,先处理中间的,注意一定要留下两刀,因为首,尾都只需要一刀就能减掉
for(i=0; i<j&&cur>2; i++) { //中间‘连续的1’,需要用两刀剪
sum+=num[i];
num[i]=0; //用完就删
cur-=2;
}
//判断最后剩下的两刀
for(i=0; i<j; i++) if(num[i]!=0) break; //找到,中间没剪去的最大‘连续的1’
if(cur>=2) { //如果剩下的刀数 >= 2,就是 num[i],pre,left1,三者之间最大的两个 (原因:请自己在草稿本上演示一下)
if(pre<=left1&&pre<=num[i]) sum+=(left1+num[i]);
else if(left1<=pre&&left1<=num[i]) sum+=(pre+num[i]);
else sum+=(left1+pre);
} else if(cur==1) { //剩下刀数 == 1,即 k==3,两种情况:1.剪中间,2.剪尾部(注意剪掉尾部的话,首部的1也可以连上去)
sum+=max(num[i],pre+left1);
}
if(k==0) printf("%d\n",pre); //k==0,就是首部的‘连续的1’
else printf("%d\n",sum);
}
return 0;
}