codeforces 213C Relay Race(DP基础,棋盘路径)

来源:互联网 发布:linux usr local bin 编辑:程序博客网 时间:2024/06/05 11:22

题意:
n×n的矩阵a, 1000<=aij<=1000
求从(1, 1)到(n,n)的两条路线(经过的格子可以重复),路线上的数值和最大,每个元素只能被取一次。
思路:
容易得出一个自然的状态表示是第k条对角线上取(k-i, i)和(k-j, j)的最大值。
用刷表法比较容易管理边界。

k, i, j // 可行状态for (int si = i;si <= i+1;++i) // si, sj走到下一条对角线上的位置    for (int sj = j;sj <= j+1;++sj) {        if (si > n || sj > n || k+1-si > n || k+1-sj > n) continue;        /*....*/    }

一个优化是
我们可以使i总是<=j,即两条路线不交叉(可以相交)。因为一旦交叉,又可以把它们看成是不交叉的。(通过翻转交叉点后的路径)

int a[Maxn+5][Maxn+5], f[Maxn+5][Maxn+5], g[Maxn+5][Maxn+5], n;int solve() {    rep(i, 1, n) rep(j, 1, n) f[i][j] = -inf;    f[1][1] = a[1][1];    rep(k, 2, n*2-1) {        rep(i, 1, n) rep(j, 1, n) g[i][j] = -inf;        rep(i, 1, n) rep(j, i, n) {            if (f[i][j] <= -inf) continue;            rep(si, i, i+1) rep(sj, j, j+1) {                if (si > sj || si > n || sj > n || k+1-si > n || k+1-sj > n) continue;                int bonus;                if (si == sj)                    bonus = a[k+1-si][si];                else                    bonus = a[k+1-si][si] + a[k+1-sj][sj];                g[si][sj] = max (g[si][sj], f[i][j] + bonus);            }        }        rep(i, 1, n) rep(j, 1, n) f[i][j] = g[i][j];    }    return f[n][n];}
0 0
原创粉丝点击