题意:
有N * N个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次。
走两次,所以状态表示要同时表示两次路径。dp[i][j][k][l] 表示第一次走到i, j,第二次走到k, l得到的最大值,这里i + j == k + l
其实第四维是可以通过前三维算出来的,所以可以去掉
那么dp[i][j][k] 可以通过四种状态转移,(i, j - 1, k) (i, j - 1, k - 1) (i - 1, j, k) (i - 1, j, k - 1)即两次都可以选择是从上或者左边移动过来
因为i + j == k + l,所以 i + j - k是l 的位置,1 <= l <= n,即 i + j <= k + n && i + j >= k + 1
#include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <vector> #include <iostream> #include <algorithm> #include <bitset> #include <fstream> using namespace std; //LOOP #define FF(i, a, b) for(int i = (a); i < (b); ++i) #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FED(i, b, a) for(int i = (b); i>= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(A,value) memset(A,value,sizeof(A)) #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++) //OTHER #define SZ(V) (int)V.size() #define PB push_back #define MP make_pair #define all(x) (x).begin(),(x).end() //INPUT #define RI(n) scanf("%d", &n) #define RII(n, m) scanf("%d%d", &n, &m) #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k) #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p) #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q) #define RS(s) scanf("%s", s) //OUTPUT #define WI(n) printf("%d\n", n) #define WS(n) printf("%s\n", n) //debug //#define online_judge #ifndef online_judge #define dt(a) << (#a) << "=" << a << " " #define debugI(a) cout dt(a) << endl #define debugII(a, b) cout dt(a) dt(b) << endl #define debugIII(a, b, c) cout dt(a) dt(b) dt(c) << endl #define debugIV(a, b, c, d) cout dt(a) dt(b) dt(c) dt(d) << endl #define debugV(a, b, c, d, e) cout dt(a) dt(b) dt(c) dt(d) dt(e) << endl #else #define debugI(v) #define debugII(a, b) #define debugIII(a, b, c) #define debugIV(a, b, c, d) #endif #define sqr(x) (x) * (x) typedef long long LL; typedef unsigned long long ULL; typedef vector <int> VI; const double eps = 1e-9; const int MOD = 1000000007; const double PI = acos(-1.0); const int INF = 0x3f3f3f3f; const int maxn = 105; int dp[maxn][maxn][maxn]; int w[maxn][maxn]; int main() { //freopen("0.txt", "r", stdin); int n; while (~RI(n)) { FE(i, 1, n) FE(j, 1, n) RI(w[i][j]); CLR(dp, 0); FE(i, 1, n) { FE(j, 1, n) { FE(k, 1, n) if (i + j >= k + 1 && i + j <= k + n) { int t = max(dp[i][j - 1][k - 1], dp[i][j - 1][k] ) + (k == i ? w[i][j] : w[i][j] + w[k][i + j - k]); if (t > dp[i][j][k]) dp[i][j][k] = t; t = max(dp[i - 1][j][k - 1], dp[i - 1][j][k]) + (k == i ? w[i][j] : w[i][j] + w[k][i + j - k]); if (t > dp[i][j][k]) dp[i][j][k] = t; } } } WI(dp[n][n][n]); } return 0; }
neu1458 方格取数 dp解法,布布扣,bubuko.com
原文地址:http://blog.csdn.net/colin_27/article/details/38413621