Noip2008传纸条题解

仍是多线程dp,这次直接斜着读入,方便写dp方程。
以6×4的图为例,读入顺序如表(从左至右,从上至下,不用管那些0)

for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j)
        read(map[i+j-1][i]);
---------
000000000
000(1,4)(2,4)(3,4)(4,4)(5,4)(6,4)
00(1,3)(2,3)(3,3)(4,3)(5,3)(6,3)0
0(1,2)(2,2)(3,2)(4,2)(5,2)(6,2)00
(1,1)(2,1)(3,1)(4,1)(5,1)(6,1)000

dp时注意除了(1,1)和(m,n)其余的要判断是否是同一个点,若是则忽略,不是则转移状态。
Code:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 110;
int map[maxn][maxn], f[maxn][maxn][maxn], n, m;
inline void read(int &a) {
    int f = 1;
    char ch = getchar();
    a = 0;
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        a = a*10 + ch - 48;
        ch = getchar();
    }
    a *= f;
}
inline void write(int a) {
    int top = 0;
    char ch[30];
    if(a < 0) { putchar('-'); a = -a; }
    do {
        ch[top++] = a%10 + 48;
        a /= 10;
    } while(a);
    while(top--) putchar(ch[top]);
    putchar('\n');
}
inline void init() {
    read(m); read(n);
    for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j)
        read(map[i+j-1][i]);
}
inline void work() {
    for(int k = 1; k < m + n; ++k)
        for(int i = 1; i < m + n; ++i) for(int j = 1; j < m + n; ++j) {
            if((i != j && k != m + n - 1) || (i == j && k == m + n - 1)) {
                f[k][i][j] = max(max(f[k-1][i-1][j-1], f[k-1][i-1][j]), max(f[k-1][i][j-1], f[k-1][i][j]));
                f[k][i][j] += map[k][i] + map[k][j];
            }
        }
    write(f[m+n-1][m][m]);//这里的点的顺序是右上到左下,所以(m,n)是第m+n-1条斜线上的第m个格子
}
int main() {
    init();
    work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值