【2019.9.23】NOIP2017 practice exam
Problem
Solution
T1.
T2.
f[i][j]表示原串使用了前i个字符,添加了j个字符后的总代价。
同时记录上一次使用的决策是哪一个。
复杂度是O((n+k)*k)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int N=10005; const int K=55; int n,k,f[N][K],lst[N][K]; char str[N]; inline void get(int x,int y){ if(lst[x][y]==1) get(x-1,y); else if(lst[x][y]==2){ get(x,y-1); printf(" %d",x+y); } } inline void dp(){ int i,t; memset(f,0x3f,sizeof(f)); f[0][0]=0; for(int a=1;a<=n+k;a++){ for(int j=max(0,a-n);j<=min(a,k);j++){ i=a-j; t=((a%10)==0); if(i&&j){ if(f[i][j]>f[i-1][j]+(t&(str[i]=='1'))){ f[i][j]=f[i-1][j]+(t&(str[i]=='1')); lst[i][j]=1; } if(f[i][j]>f[i][j-1]+t){ f[i][j]=f[i][j-1]+t; lst[i][j]=2; } } else if(i){ f[i][j]=f[i-1][j]+(t&(str[i]=='1')); lst[i][j]=1; } else{ f[i][j]=f[i][j-1]+t; lst[i][j]=2; } } } int ans=0; for(int j=1;j<=k;j++) if(f[n][ans]>f[n][j]) ans=j; printf("%d\n",f[n][ans]); printf("%d",ans); get(n,ans); } int main(){ freopen("crew.in","r",stdin); freopen("crew.out","w",stdout); scanf("%d%d",&n,&k); scanf("%s",str+1); dp(); return 0; }