bapc2012 D\Digital Transmission DP
题意:输入一行不超过100 000的比特流,由 "0","1","."组成,"."可以表示0也可以表示1。
要求:①该比特流不能存在两个连续的00或者11
②该比特流必须满足1个总个数和0的总个数相等
问:是否存在满足要求的合法情况,满足输出yes,否则输出no
思路:比赛的时候虽然看着像是DP,but实际上一点思路也没~想不到怎样能够满足即相等又不连续,2^len一定会超时~
赛后看了解题报告感觉很好~
先判断该比特流本身是否合理(要求1和要求2)
不合理输出no,否则检查
往该比特流的"."填写1,第一次,在满足要求①的情况下,尽量多的填写1,求出r;
第二次,在满足要求②的情况下,尽量少的填写1,求出l;如果l<=len/2<=r/2,输出yes,否则输出no.
(shine小朋友的暴力想法)
证明:
1最多的情况莫过于110110110110...
1最少的情况莫过于001001001001...
减少一个1,那么只需要把一个1变成0就可以了,例如
110110110110...-->100110110110...
如此,每种l到r中的状态都可以达到,然后dp求出l和r
dp思路:(很暴力)
dp[i][0][1]=max( dp[i-1][0][0],dp[i-1][1][0] )+1;
dp[i][1][1]=dp[i-1][0][1]+1;
dp[i][1][0]=max(dp[i-1][0][1],dp[i-1][1][1]);
dp[i][0][0]=dp[i-1][1][0];
代码写的很暴力。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int N=100010; 8 char str[N]; 9 int c0,c1,flag,len; 10 int dp[N][2][2]; 11 12 int max(int a,int b){return a>b?a:b;} 13 int min(int a,int b){return a<b?a:b;} 14 15 int DP(int u,int v){ 16 if(str[0]=='0'+u){ 17 dp[0][u][v]=dp[0][v][v]=0; 18 dp[0][v][u]=dp[0][u][u]=0; 19 }else { 20 dp[0][u][v]=dp[0][v][v]=1; 21 dp[0][v][u]=dp[0][u][u]=0; 22 } 23 for(int i=1;i<len;i++){ 24 if(str[i]=='0'+u){ 25 dp[i][u][v]=dp[i][v][v]=0; 26 dp[i][u][u]=dp[i-1][v][u]; 27 dp[i][v][u]=max(dp[i-1][u][v],dp[i-1][v][v]); 28 }else if(str[i]=='0'+v){ 29 dp[i][u][u]=dp[i][v][u]=0; 30 dp[i][u][v]=max(dp[i-1][u][u],dp[i-1][v][u])+1; 31 dp[i][v][v]=dp[i-1][u][v]+1; 32 }else{ 33 dp[i][u][v]=max(dp[i-1][u][u],dp[i-1][v][u])+1; 34 dp[i][v][v]=dp[i-1][u][v]+1; 35 dp[i][v][u]=max(dp[i-1][u][v],dp[i-1][v][v]); 36 dp[i][u][u]=dp[i-1][v][u]; 37 } 38 } 39 int maxa=0; 40 for(int i=0;i<2;i++) 41 for(int j=0;j<2;j++) 42 maxa=max(maxa,dp[len-1][i][j]); 43 return maxa; 44 } 45 46 int main(){ 47 int T; 48 int i,j; 49 50 scanf("%d",&T); 51 getchar(); 52 while(T--){ 53 scanf("%s",str); 54 len=strlen(str); 55 flag=c0=c1=0; 56 for(i=0;i<len;i++){ 57 if(str[i]=='0') c0++; 58 else if(str[i]=='1') c1++; 59 if(i>1&&str[i]!='.'&&str[i]==str[i-1]&&str[i-1]==str[i-2]) 60 flag=1; 61 } 62 if((len&1)||flag||(c0>len/2)||(c1>len/2)){ 63 puts("no"); 64 continue; 65 } 66 67 int l=len-DP(1,0); 68 int r=DP(0,1); 69 70 puts( (len/2>=l&&len/2<=r)?"yes":"no" ); 71 } 72 return 0; 73 }
就这道题而言,感觉一直在考虑①②同时满足的去填写,没想到求区间。。。