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

题意:
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值