【dp】10-15題解 snake vs block


snake vs block

題目描述

Tgopknight最近迷上了一款叫做Snake vs Block的游戲,他總覺得他自己玩出的不是最優解,但是他忙於享受游戲的樂趣,只好請你幫忙找出最優解。

Snake vs Block共有n5列的格子,每個格子上有磚塊或者豆豆或者啥也沒有,同行相鄰格子 之間可能有擋板,磚塊和豆豆有對應的數值,蛇的初始長度是4,在第1行第3列上,每吃一個豆豆可以增加相應長度,撞上一個磚塊會減少相應長度,並且得到相應分數,蛇不能穿過擋板,長度小於零 即死亡(臨死前撞的磚塊不記得分),死亡或到達終點離開第n行)游戲結束。

由於Tgopknight手速極快,他每前進到一行可以在這一行內任意移動,除非撞到擋板,他現在想知道他可以拿到的最高分是多少。

輸入輸出

input

第一行輸入一個正整數n,表示格子的行數

后接n行,每行5個數,第i行第j個表示第i行第j列的格子,為ai,j,若ai,j<=0,則表示該格子上有個數 值為|ai,j|的磚塊,若ai,j,則表示該格子上有個數值為ai,j的豆豆,若ai,j=0,則表示該格子上什么也沒有

第n+2行輸入一個整數m,表示擋板的個數。

后接m行,每行兩個數x,y,表示第x行第y和第y+1列之間有擋板。

output

輸出一行,一個正整數,為得到他能得到的最高分方案數

樣例

input

output

數據范圍

對於30%的數據n < 5

另有20%的數據m = 0

另有20%的數據保證所有磚塊所在的行數都比豆豆所在的行數大

對於 100%的數據1 <= n < =200,-10 <=ai,j < =10,0 <= m <= min(n * 4, 200),1 <= x < =n,1 <=y <= 4

數據保證第1行第3列上沒有東西

數據有梯度

思路

 

把豆豆和磚塊丟在一起dp即可。

令 f[i][j][k] 表示前i行,蛇的長度還剩下j,從第k列離開第i行的最大得分。

令 g[j1][1][r] 表示蛇的長度還剩下j1,當前行在第1列到第r列之間移動后仍然未死亡的最大得分。

 f[0][4][3]=0 為初始狀態。

對於每個i,首先令 g[j1][k][k] = f[i - 1][j1 - a[i][k]][k]+max(-a[i][k],0) 為初始狀態。

狀態轉移方程為 g[j1][1][r] = max(g[j1-a[i][1]][1+1][r] +max(-a[i][j],0),g[j1-a[i][r]][1][r- 1] +max(-a[i][k], 0)) 

最后 f[i][j][k] = max{g[j][1][r](1<= l <= k<= r <= 5)} 

        ans = max{f[i][j][k]} 

具體做法參考std。

時間復雜度o(n * (max(ai,j) * n) )

代碼

#include <bits/stdc++.h>
using namespace std;
int n, a[205][5],m,x,y,f[205][10005][5]={{{0}}};
int g[10005][5][5] = {{{0}}}, maxi, ans = 0;
bool flag[205][4] = {{false}};
int main() {
	freopen("snakevsblock.in","r",stdin);
	freopen("snakevsblock.out","w",stdout);
	scanf("%d",&n);
	for (int i=1; i<=n; i++)
		for (int j=0; j<5; j++)
			scanf("%d",&a[i][j]);
	scanf("%d", &m);
	for (int i=1; i<=m; i++) {
		scanf("%d%d", &x, &y);
		flag[x][y-1] = true;   //設置擋板 
	}
	memset(f, -0x7f7f7f, sizeof(f));
	f[0][4][2]=0;
	maxi=n*50;
	for(int i=1; i<=n;i++) {
		memset(g,-0x7f7f7f, sizeof(g));
		for (int j = 0; j<=maxi; j++)
			for (int k =0; k<5; k++)
				if (j-a[i][k]>= 0 && j-a[i][k]<=maxi)
					f[i][j][k]=g[j][k][k]=f[i-1][j-a[i][k]][k]+max(-a[i][k], 0);    //初始化 
		for (int l = 1; l <= 4; l++)
			for (int j=0, k=j+l; k<5;j++,k++)
				for (int v=0,val; v<=maxi; v++) {
					/*擋板情況分類討論*/ 
					if (!flag[i][j] && (val=v-a[i][j]) >=0 && val<=maxi) g[v][j][k]=g[val][j+1][k]+max(-a[i][j],0);           
					if (!flag[i][k-1] && (val=v-a[i][k])>=0&& val<=maxi) g[v][j][k]=max(g[v][j][k],g[val][j][k-1]+max(-a[i][k],0));
					
					for (int to = j; to <= k; to++) f[i][v][to]=max(f[i][v][to], g[v][j][k]);
				}
	}
	for (int l=0;l<=n;l++)
		for (int i=0; i<=maxi;i++)
			for (int j=0;j<5;j++)
				ans=max(ans,f[l][i][j]);
	printf("%d\n", ans);
	return 0;
}

  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM