1. 程式人生 > >牛客訓練賽36 B題(dp滾動陣列)

牛客訓練賽36 B題(dp滾動陣列)

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