牛客訓練賽36 B題(dp滾動陣列)
阿新 • • 發佈:2019-01-05
2019年第一次比賽,遭逢大敗。。。都不忍心看自己的排名,第一題一直在想該怎麼去優化。發現並不用,直接暴力過。。。心態炸了,第二題是dp題,一開始想到了增加維度以獲得更多資訊,還好死不死的用疲勞度作為第二維。。。結果陣列變成400*81000那麼大。。。一直在推狀態轉移方程還推不出來。。。看了題解恍然大悟。。。哎,在推不出狀態轉移方程的時候應該改變思路,想辦法減小每一維的大小,這樣就比較容易想到正確的辦法,具體看題解;
這題還有一個坑點就是如果不用滾動陣列,會爆記憶體。。。
程式碼如下:
/* 想到了擴充維度來獲取更多資訊。但是把疲勞度作為了第二維。。。所以一直轉移不出來 dp[i][j][k]:第i天,已經工作了j天,已經連續工作了k天,剩餘的疲勞度 ans=max(j); 滾動陣列 */ #define LOCAL #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; #define maxn 2100 #define inf 40000000 typedef pair<int,int >P; int d[2][410][410];//每個狀態下的最大收益 int n,m; char s[410]; int main() { #ifdef LOCAL //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); #endif scanf("%d%d",&n,&m); scanf("%s",s+1); int maxx=0; int ans=0; memset(d,-1,sizeof(d)); d[0][0][0]=m; int cur=1; for(int i=1;i<=n;i++) { int j; for(j=0;j<=n;j++) { for(int k=0;k<=n;k++) { d[cur][j][0]=max(d[cur][j][0],d[cur^1][j][k]); } } if(d[cur][j][0]>=0) ans=max(ans,j); if(s[i]=='1') { for(int j=1;j<=n;j++) { for(int k=1;k<=n;k++) { d[cur][j][k]=max(d[cur][j][k],d[cur^1][j-1][k-1]-k); if(d[cur][j][k]>=0) ans=max(ans,j); } } } cur^=1; } printf("%d\n",ans); return 0; }