方格取数

题目链接

  • 题意:

    有N * N个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次。求SUM的最大值

    (1 <= N <= 100),(0 <= value <= 1000)

  • 分析:

    首先明白,两条线路除了起点和终点,一定不会相交,因为如果一旦相交,总可以找到一种方案使得不想交且结果不会更差。那么,就可以DP解决:dp[step][x][xx],表示现在两个人已经走了step步,第一个人在x行,第二个在xx行。这里有一个很重要的前提:如果需要保证两个路径不重复,那么在step相同的时候,两个人只要不在同一个点上,那么就可以保证两个线路没有交点。

const int MAXN = 110;

int dp[2][MAXN][MAXN], ipt[MAXN][MAXN];
int n;

inline bool check(int x)
{
    return x >= 0 && x < n;
}

inline void Max(int step, int now, int x, int xx, int tx, int txx)
{
    int ty = step + 1 - tx, tyy = step + 1 - txx;
    if (!check(tx) || !check(ty) || !check(txx) || !check(tyy))
        return;
    if (step != n + n - 3 && tx == txx && ty == tyy)
        return;
    int val = dp[now][x][xx] + ipt[tx][ty] + ipt[txx][tyy];
    if (dp[now ^ 1][tx][txx] < val)
        dp[now ^ 1][tx][txx] = val;
}

int main()
{
    while (~RI(n))
    {
        REP(i, n) REP(j, n)
            RI(ipt[i][j]);
        if (n == 1)
        {
            WI(ipt[0][0]);
            continue;
        }
        int step = n + n - 2, now = 0;
        CLR(dp, -1); dp[now][0][0] = ipt[0][0];
        REP(s, step)
        {
            REP(i, n) REP(j, n)
            {
                int x = i, y = s - i, xx = j, yy = s - j;
                if (!check(x) || !check(y) || !check(xx) | !check(yy) || !~dp[now][x][xx])
                    continue;
                Max(s, now, i, j, i, j);
                Max(s, now, i, j, i + 1, j);
                Max(s, now, i, j, i, j + 1);
                Max(s, now, i, j, i + 1, j + 1);
            }
            CLR(dp[now], -1);
            now ^= 1;
        }
        cout << dp[now][n - 1][n - 1] - ipt[n - 1][n - 1] << endl;
    }
    return 0;
}

方格取数

时间: 2024-12-29 11:41:54

方格取数的相关文章

hdu 1565 方格取数(2)(网络流之最大点权独立集)

题目链接:hdu 1565 方格取数(2) 题意: 有一个n*m的方格,每个方格有一个数,现在让你选一些数.使得和最大. 选的数不能有相邻的. 题解: 我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有: 最大点权独立集 + 最小点权覆盖集 = 总点权和, 这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图, 1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一

P1004 方格取数

P1004 方格取数 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 14 0 0 0 0 0 21 0 0 0 4 0 0 0 0 15 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . B 某人从图的左上角的A点出发,可以向下行走,也可以向右走,直到到达右下角

hdoj 1569 方格取数(2) 【最小割】 【最大点权独立集】

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5589    Accepted Submission(s): 1741 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

1475: 方格取数

1475: 方格取数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 578  Solved: 309[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. Input 第一行一个数n:(n<=30) 接下来n行每行n个数描述一个方阵 Output 仅一个数,即最大和 Sample Input 2 1 2

hdu 1569 方格取数(2) 网络流 最大点权独立集

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5146    Accepted Submission(s): 1610 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

HDU 1565 方格取数(1) (状态压缩 DP)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5779    Accepted Submission(s): 2194 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

HDU 1565 方格取数(1)(状压dp)

感觉这道题目的数据比较水啊,程序的时间复杂度为1711^2*20竟然也可以过掉....其他的就是状压了啊,注意需要滚动一下啊.... 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5701    Accepted Submission(s): 2159 Problem Description 给你一个n*n的格子的棋

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

hdu 4859 最大点权独立集的变形(方格取数的变形)

/*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps: 和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf.然后和方格取数差不多的建图 .--.||E权值为2,,.||E--D权值为0. 最大点权独立集=sum-最小点权覆盖. */ #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 0x3ffff

【网络流】hdu 1569 方格取数(2)

/* 和1565一样: 总点数的权 - 最小覆盖点集 = 最大独立集 -------------------------------------- void add(int u, int v, int f)加边 { e[ct].u = u; e[ct].v = v; e[ct].f = f; next[ct] = first[u]; first[u] = ct++; e[ct].u = v; e[ct].v = u; e[ct].f = 0; next[ct] = first[v]; first