Martian Mining(poj 2948)
原题链接
二维dp会存在状态的相互影响的问题。
由于临近精炼厂的位置会影响到相应传输的状态,状态压缩dp->但是n和m的范围多达500无法进行压缩,仅仅只记录两个边上的状态远远不够
那么,继续分析题目的特点
不难发现,从西向东,南北方向的传送带长度是非降的,从北向南,东西方向的传送带的长度也是非降的。
思路一:
根据题目的特性,dp[i][j] 代表第i列状态为前j个为南北 向的管道,其余为东西向的管道时,最大的运输量。sum[i][j]代表第i列前j个为南北向的管道,其余为东西向的管道时,第i列的值之和。由此,可以得到状态转移方程为:
dp[i][j]=max{dp[i-1][k]}(k<=j) + sum[i][j]
#include<iostream>
#include<algorithm>
using namespace std;
#define NMAX 505
int dp[NMAX][NMAX];
int sum[NMAX][NMAX];
int y[NMAX][NMAX];
int b[NMAX][NMAX];
int n, m;
int main() {
while (1) {
scanf_s("%d %d", &n, &m);
if (n == 0 && m == 0) break;
int u = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf_s("%d", &y[i][j]);//注意scanf_s是进行格式化的匹配的
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf_s("%d", &b[i][j]);
}
}
//预处理出所有的情况
for (int i = 0; i < m; i++) {
for (int j = 0; j <= n; j++) { //从0到n,注意n是全部填满的情况
sum[i][j] = 0;
int k;
for (k = 0; k < j; k++) sum[i][j] += b[k][i];
for (; k < n; k++) sum[i][j] += y[k][i];
if (i == 0) dp[0][j] = sum[0][j];
//printf("%d ", sum[i][j]);
}
//cout << endl;
}
for (int i = 1; i < m; i++) { //从第一列开始,第0列已经被初始化
for (int j = 0; j <= n; j++) {
dp[i][j] = 0;
for (int k = 0; k <= j; k++) {
dp[i][j] = max(dp[i][j], dp[i - 1][k] + sum[i][j]);
}
}
}
//最后遍历所有的可能性
int res = 0;
for (int i = 0; i <= n; i++) {
res = max(res, dp[m - 1][i]);
}
printf("%d\n", res);
}
}
总结
第一次自己做出了一道dp,前面的dp刷题记录还在难产中,这次成功的经历让我意识到,对于题目抽丝剥茧的分析是至关重要的,结合题目所给出的特性再进行解题,才是正道。