Transmission Delay 传输谍延时 bzoj-1581 Usaco-2009 Hol
题目大意:题目链接。
注释:略。
想法:
动态规划。
首先我们考虑从后往前dp。(最近好多题都是从后往前啊)。
这个题就是如此。
状态:dp[i][j]表示i~n中用了j个1的方案数。
第一问中我们只需要加就行了。
第二问,如果当前位是0的方案比k大,那么我们将这位上添0;
如果当前位是0的方案比k小,我们将这位添1。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=2010; const int MOD=1e8; int n,d,k,cnt0=0,cnt1=0; int p0[N],p1[N],f[N][N],g[N][N]; char s[N]; int main() { scanf("%d%d%d",&n,&d,&k); scanf("%s",s+1); for(int i=1;i<=n;i++) if(s[i]=='0')p0[++cnt0]=i; else p1[++cnt1]=i; f[n+1][0]=g[n+1][0]=1; for(int i=n;i>=1;i--) for(int j=0;j<=min(n-i+1,cnt0);j++) { int k=n-i+1-j; if(j&&abs(p0[cnt0-j+1]-i)<=d) { f[i][j]+=f[i+1][j-1]; if(f[i][j]>MOD)f[i][j]-=MOD; g[i][j]=min(g[i][j]+g[i+1][j-1],MOD+1); } if(k&&abs(p1[cnt1-k+1]-i)<=d) { f[i][j]+=f[i+1][j]; if(f[i][j]>MOD) f[i][j]-=MOD; g[i][j]=min(g[i][j]+g[i+1][j],MOD+1); } } printf("%d ",f[1][cnt0]); int s0=cnt0,s1=cnt1; for(int i=2;i<=n;i++) { if(s0&&abs(p0[cnt0-s0+1]-i+1)<=d) { if(g[i][s0-1]>=k)s0--,putchar('0'); else s1--,k-=g[i][s0-1],putchar('1'); } else s1--,putchar('1'); } if(s0) putchar('0'); else putchar('1'); return 0; }
小结:好题!