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];

代码写的很暴力。。。

 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 }
View Code


就这道题而言,感觉一直在考虑①②同时满足的去填写,没想到求区间。。。

posted @ 2013-05-13 21:12  _sunshine  阅读(354)  评论(0编辑  收藏  举报