我好菜我好菜我好菜我好菜我好菜我好菜我好菜我好菜我好菜我好菜我好菜
[题目]:https://www.luogu.org/problemnew/show/P1004
[思路]
一开始想的是先dp第一遍, 再将走过的置零(hdg教的我逆推), 再dp第二遍.
然而WA了之后, hdg告诉我先让第一个人走最优可能会让总体走不了最优.
所以要枚举两个人的所有的状态, 4维dp存储两个人的位置.
转移方程:
(如果两个人走到同一个位置, 一个数当然只能取一次)
边界:
dp[1][1][1][1]=mp[1][1][1][1]
dp带0的都是0
[代码]
#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;
const int M=2e5+5;
const int inf=1e9+5;
int dp[10][10][10][10];
int mp[10][10]= {0};
int n;
int go[4][4]= {
1,0,1,0,
1,0,0,1,
0,1,1,0,
0,1,0,1
};
int main() {
scanf("%d",&n);
int x,y,z;
while(1) {
scanf("%d%d%d",&x,&y,&z);
if((x||y||z)==0)
break;
mp[x][y]=z;
}
memset(dp,0,sizeof(dp));
for(int a=1; a<=n; a++) {
for(int b=1; b<=n; b++) {
for(int c=1; c<=n; c++) {
for(int d=1; d<=n; d++) {
if(a==b&&b==c&&c==d&&d==1) {
dp[a][b][c][d]=mp[a][b];
} else {
int add=0;
for(int i=0; i<4; i++) {
add=max(add,dp[a-go[i][0]][b-go[i][1]][c-go[i][2]][d-go[i][3]]);
}
dp[a][b][c][d]+=add+mp[a][b]+mp[c][d];
if(a==c&&b==d)
dp[a][b][c][d]-=mp[c][d];
}
}
}
}
}
printf("%d\n",dp[n][n][n][n]);
return 0;
}