唉,dp还是不行,多加努力。
第1行:N,N为矩阵的大小。(2 <= N <= 500) 第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值。(1 <= N[i] <= 10000)
输出能够获得的最大价值。
3 1 3 3 2 1 3 2 2 1
11
入门级dp,直接记录状态转移即可。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
const int INF=1000000007;
const int MAXN =1010;
const int MAXM=1000010;
const int MODE=1000000007;
int dp[MAXN][MAXN];
int a[MAXN][MAXN];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
dp[i][j]=-INF;
}
dp[1][1]=a[1][1];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dp[i][j]=max(dp[i][j],max(dp[i-1][j],dp[i][j-1])+a[i][j]);
}
}
printf("%d\n",dp[n][n]);
}
第1行:2个数M N,中间用空格分隔,为矩阵的大小。(2 <= M, N <= 200) 第2 - N + 1行:每行M个数,中间用空格隔开,对应格子中奖励的价值。(1 <= A[i,j] <= 10000)
输出能够获得的最大价值。
3 3 1 3 3 2 1 3 2 2 1
17
一个从左上到右下,另一个右下到左上。相当于是有两个同时从左上到右下。走到相同处就只记录一次。
如果用dp[x1][y1][x2][y2]记录会超内存。
但是因为是同时前进,dp[x1][x2][k]记录即可,有了前进步数就能知道y坐标。
具体的看代码。
注意是先读m再读n
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
const int INF=1000000007;
const int MAXN =210;
const int MAXM=1000010;
const int MODE=1000000007;
int a[MAXN][MAXN];
int dp[MAXN][MAXN][MAXN*2];
int main(){
int n,m;
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int k=2;k<=(n+m+1);k++){
int t=min(n,k);
for(int x1=1;x1<=t;x1++){
for(int x2=1;x2<=t;x2++){
int y1=k-x1;
int y2=k-x2;
int ans=max(max(dp[x1-1][x2][k-1],dp[x1][x2-1][k-1]),max(dp[x1-1][x2-1][k-1],dp[x1][x2][k-1]));
if(x1==x2)
ans+=a[x1][y1];
else
ans+=a[x1][y1]+a[x2][y2];
if(ans>dp[x1][x2][k]){
dp[x1][x2][k]=ans;
}
}
}
}
printf("%d\n",dp[n][n][n+m+1]);
}
第一行两个整数m, n (0 < m, n < 10),表示矩阵的行数和列数。 后面m行,每行n个整数表示矩阵里的数,整数范围[-10000000, +10000000]。
一个整数表示最大得分。
3 3 -1 2 -3 -4 5 -6 -10 3 2
12
把结题报告贴上供大家一起学习。
状态表示,用蓝色的边界线表示状态。
每个格子可能是如下几种情况,具体选择,取决于边界线上每个格子“对外”的情况。
边界线对外可以是入(IN),出(OUT),和无(NONE)。注意“无”可能是左下角或者左上角的情况,即消耗掉一个IN,一个OUT。
如何表示边界线(蓝线)上的状态?
可以用0,1,2表示一个格子的状态,这样所有格子可以用二进制压缩,每个格子占2bit。每决定一个新格子,考虑它左面和上面格子的状态,来枚举当前格子的状态。注意点:
(1) 蓝色边界线上#IN = #OUT,即IN, OUT的总数相等
(2) 连接一个格子的时候,可能会修改之后的IN, OUT (反向)
(3) NONE不一定是没经过(如前所述),可以是抵消一对IN和 OUT。
状态表示dp[x][y][state] 表示当前在(x,y)时,IN-OUT状态(二进制整数)state的最大的分。
dp[x][y]与dp[x][y-1][state]有关。
具体插头dp细节可以参看国家集训队论文 <基于连通性状态压缩的动态规划问题>