20170907
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20170907相关的知识,希望对你有一定的参考价值。
题意:给出一个由n个0或1组成的序列s1,...,sn,删去一些0或1使得在任何一个1的后面都没有0。求剩下的数的数量的最大值。
方法:扫一遍先(递推)预处理出b和c数组,然后再枚举i,对于每个枚举出的i删去i之前的所有0与i及i之后的所有1,然后记录剩下数量的最大值。
思考:可以只记录前缀和,前缀和就表示了某个数及之前的数中1的数量,0的数量就是这个数的序号减去1的数量。
1 #include<cstdio> 2 int a[110]; 3 int b[110];//b[i]表示第i个数及其之后的0的数量 4 int c[110];//c[i]表示第i个数之前的1的数量 5 int minn=0x3f3f3f3f,n; 6 int min(int a,int b) 7 { 8 return a>b?b:a; 9 } 10 int main() 11 { 12 int i; 13 scanf("%d",&n); 14 for(i=1;i<=n;i++) 15 scanf("%d",&a[i]); 16 for(i=n;i>=1;i--) 17 { 18 b[i]=b[i+1]; 19 if(a[i]==0) b[i]++; 20 } 21 for(i=1;i<=n;i++) 22 { 23 c[i]=c[i-1]; 24 if(a[i-1]==1) c[i]++; 25 } 26 c[n+1]=c[n]+(a[n]==0?0:1); 27 for(i=1;i<=n+1;i++)//注意:需要循环到n+1.曾经就错在这里,没有考虑删去最后一个及之前的所有1 28 minn=min(minn,c[i]+b[i]); 29 if(c[n]==0) minn=0; 30 printf("%d",n-minn); 31 return 0; 32 }
方法2:直接最长不下降子序列水过(没想到)
对拍程序(暴力子集生成)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int ans=-1,n; 5 int a[110]; 6 int judge(int k) 7 { 8 int i; 9 int ans=0; 10 bool f1=false; 11 for(i=0;i<n;i++) 12 if((1<<i)&k) 13 { 14 ans++; 15 if(!f1) 16 { 17 18 if(a[i]==1) 19 f1=true; 20 } 21 else 22 { 23 if(a[i]==0) 24 return -1; 25 } 26 } 27 return ans; 28 } 29 int main() 30 { 31 int i,aa; 32 scanf("%d",&n); 33 for(i=0;i<n;i++) 34 scanf("%d",&a[i]); 35 int k=(1<<n)-1; 36 for(i=0;i<=k;i++) 37 { 38 aa=judge(i); 39 if(aa) 40 ans=max(ans,aa); 41 } 42 printf("%d",ans); 43 return 0; 44 }
T2
T3
![CDATA[
$("#t2_2").load("//www.cnblogs.com/hehe54321/p/cf-846b.html>