D 牛牛的01限定串 传纸条、走下去类型的模型题
链接:https://ac.nowcoder.com/acm/contest/5531/D
题解链接:https://ac.nowcoder.com/discuss/424000?type=101&order=0&pos=34&page=1
思路:这是一道传纸条、走下去类型的模型题;
但假如这方面做的不够多的话,还是很难想到的。。。
思路在上方题解链接
具体情况注释在代码中
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int MAXN=1e3+10; 5 long long val[MAXN][MAXN]; 6 long long dp1[MAXN][MAXN],dp2[MAXN][MAXN]; 7 char s[MAXN],t[MAXN]; 8 int n,cnt0,cnt1,valpre,valsuf; 9 10 int main(){ 11 scanf("%d%d%d%d%d",&n,&cnt0,&cnt1,&valpre,&valsuf); 12 scanf("%s%s",s+1,t+1); 13 //初始化 14 for(int i=0;i<=n;i++) 15 for(int j=0;j<=n;j++) 16 dp1[i][j]=-2e18,dp2[i][j]=2e18; 17 int x=0,y=0; 18 for(int i=1;i<=n;i++){ 19 if(s[i]=='1')x++; 20 else y++; 21 if(x<=cnt1&&y<=cnt0)val[x][y]+=valpre; 22 } 23 //把相似前缀的情况枚举,记录权值 24 x=cnt1,y=cnt0; 25 for(int i=n;i;i--){ 26 if(s[i]=='1')x--; 27 else y--; 28 if(x>=0&&y>=0)val[x][y]+=valsuf; 29 } 30 //把相似后缀的情况枚举,记录权值 31 dp1[0][0]=dp2[0][0]=val[0][0]; 32 33 //跑矩阵的时候,类似于走下去模型,只能向下或者向右走 34 //但是,这道题还有一个限制,就是在某一步可能会限制只能向下或者向右 35 //假如是‘?’ 就没限制,假如是‘0’或者‘1’就有限制 36 for(int i=0;i<=cnt1;i++){ 37 for(int j=0;j<=cnt0;j++){ 38 if(i+j==0)continue; 39 if(t[i+j]=='1'&&i){ 40 dp1[i][j]=max(dp1[i][j],dp1[i-1][j]+val[i][j]); 41 dp2[i][j]=min(dp2[i][j],dp2[i-1][j]+val[i][j]); 42 }else if(t[i+j]=='0'&&j){ 43 dp1[i][j]=max(dp1[i][j],dp1[i][j-1]+val[i][j]); 44 dp2[i][j]=min(dp2[i][j],dp2[i][j-1]+val[i][j]); 45 }else if(t[i+j]=='?'){ 46 if(j)dp1[i][j]=max(dp1[i][j],dp1[i][j-1]+val[i][j]); 47 if(j)dp2[i][j]=min(dp2[i][j],dp2[i][j-1]+val[i][j]); 48 if(i)dp1[i][j]=max(dp1[i][j],dp1[i-1][j]+val[i][j]); 49 if(i)dp2[i][j]=min(dp2[i][j],dp2[i-1][j]+val[i][j]); 50 } 51 } 52 } 53 printf("%lld %lld",dp2[cnt1][cnt0],dp1[cnt1][cnt0]); 54 return 0; 55 }