【01揹包】#洛谷# P1004 方格取數
方格取數
題目
設有N \times NN×N的方格圖(N \le 9)(N≤9),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字00。如下圖所示(見樣例):
A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 14 0 0 0 0 0 21 0 0 0 4 0 0 0 0 15 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 B 某人從圖的左上角的AA點出發,可以向下行走,也可以向右走,直到到達右下角的BB點。在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字00)。 此人從AA點到BB點共走兩次,試找出22條這樣的路徑,使得取得的數之和為最大。
輸入
輸入的第一行為一個整數NN(表示N \times NN×N的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的00表示輸入結束。
輸出
只需輸出一個整數,表示22條路徑上取得的最大的和。
輸入樣例
8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0
輸出樣例
67
解題思路
做這道題我用了01揹包的做法 再把空間複雜度再降到O(n^2) 我們考慮兩個人同時走 所以狀態轉移方程為: f[i][j][k][l]=max(f[i-1][j][k-1][l],f[i-1][j][k][l-1],f[i][j-1][k-1][l],f[i][j-1][k][l-1])+a[i][j]+a[k][l];f[i][j][k][l]=max(f[i−1][j][k−1][l],f[i−1][j][k][l−1],f[i][j−1][k−1][l],f[i][j−1][k][l−1])+a[i][j]+a[k][l] 但這樣要判斷 i=k&&j=l 的情況。
#include<iostream>
#include<cstdio>
using namespace std;
int f[20][20][20][20],a[20][20],n,x,y,z;
int main()
{
scanf("%d%d%d%d",&n,&x,&y,&z);
while(x!=0||y!=0||z!=0)
{
a[x][y]=z;
scanf("%d%d%d",&x,&y,&z);
}
for(int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
for(int l=1;l<=n;l++){
f[i][j][k][l]=max(max(f[i-1][j][k-1][l],f[i-1][j][k][l-1]),max(f[i][j-1][k-1][l],f[i][j-1][k][l-1]))+a[i][j]+a[k][l];
if(i==k&&l==j)
f[i][j][k][l]-=a[i][j];
}
cout<<f[n][n][n][n];
return 0;
}