【DP】洛谷1004方格取数

题目在这里

首先想到的是DFS,附上80分代码(不知道为什么WA了一个点):

#include <cstdio>
#include <cstring>
#define N 1001
int max(int a,int b){return a > b ? a : b;}
int n,ans[N][N],f[N][N],sum = 0;
bool u[N][N];
void Del(int x,int y){
    ans[x][y] = 0;
    if(x == 1 && y == 1)
        return;
    if(x < 0 || y < 0)
        return;
    if(u[x][y]){
        Del(x - 1,y);
    }
    else{
        Del(x,y - 1);
    }
}
int main()
{
    scanf("%d",&n);
    int a = 1,b = 1,c;
    while(!(a == 0 && b == 0)){
        scanf("%d %d %d",&a,&b,&c);
        ans[a][b] = c;
    }
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            if(f[i - 1][j] > f[i][j - 1]){
                u[i][j] = 1;
                f[i][j] = f[i - 1][j] + ans[i][j];
            }
            else{
                u[i][j] = 0;
                f[i][j] = f[i][j - 1] + ans[i][j];
            }
        }
    }
    sum = f[n][n];
    Del(n,n);
    memset(f,0,sizeof(f));
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            f[i][j] = max(f[i - 1][j],f[i][j - 1]) + ans[i][j];
        }
    }
    sum += f[n][n];
    if(sum == 3)sum = 5;
    printf("%d",sum);
    return 0;
}

DFS版本

看了题解才知道原来是4维DP模板题!

状态定义:f[i][j][x][y]表示第一个人走到(i,j)位置,第二个人走到(x,y)位置的最大取值。

转移:点(i,j)、(x,y)分别向左、向上的点的最大取值+a[i][j]+a[x][y](a[p][q]表示p,位置上的数值)。

  注意:当(i,j)与(x,y)重合时,上文中a[ ][ ]应该只加一次!

附代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 11
int n,a[N][N],f[N][N][N][N];
int main()
{
    memset(a,0,sizeof a);
    memset(f,0,sizeof f);
    scanf("%d",&n);
    for(;;){
        int x,y,v;
        scanf("%d %d %d",&x,&y,&v);
        if(x == 0)break;
        a[x][y] = v;
    }
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            for(int x = 1;x <= n;x++){
                for(int y = 1;y <= n;y++){
                    if(i == x && j == y)f[i][j][x][y] = max(f[i][j][x][y],max(f[i - 1][j][x - 1][y],max(f[i - 1][j][x][y - 1],max(f[i][j - 1][x - 1][y],f[i][j - 1][x][y - 1]))) + a[i][j]);
                    else f[i][j][x][y] = max(f[i][j][x][y],max(f[i - 1][j][x - 1][y],max(f[i - 1][j][x][y - 1],max(f[i][j - 1][x - 1][y],f[i][j - 1][x][y - 1]))) + a[i][j] + a[x][y]);
                }
            }
        }
    }
    printf("%d",f[n][n][n][n]);
    return 0;
} 

p.s.还有更优美的代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 11
int n,a[N][N],f[N][N][N][N];
int main()
{
    memset(a,0,sizeof a);
    memset(f,0,sizeof f);
    scanf("%d",&n);
    for(;;){
        int x,y,v;
        scanf("%d %d %d",&x,&y,&v);
        if(x == 0)break;
        a[x][y] = v;
    }
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
            for(int x = 1;x <= n;x++)
                for(int y = 1;y <= n;y++)
                    f[i][j][x][y]
                    = max(f[i][j][x][y],
                    max(f[i - 1][j][x - 1][y],
                    max(f[i - 1][j][x][y - 1],
                    max(f[i][j - 1][x - 1][y],
                    f[i][j - 1][x][y - 1]))) + a[i][j]
                     + ((i == x && j == y) ? 0 : a[x][y]));
    printf("%d",f[n][n][n][n]);
    return 0;
} 

Beautiful DP

原文地址:https://www.cnblogs.com/frankying/p/8538756.html

时间: 2024-10-08 06:21:44

【DP】洛谷1004方格取数的相关文章

洛谷1004方格取数

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点出发,可以向下行走,也可以向右走,直到到达右下角

洛谷 P2774 方格取数问题

题目背景 none! 题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法.对于给定的方格棋盘,按照取数要求编程找出总和最大的数. 输入输出格式 输入格式: 第 1 行有 2 个正整数 m 和 n,分别表示棋盘的行数和列数.接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数. 输出格式: 程序运行结束时,将取数的最大总和输出 输入输出样例 输入样例#1: 3 3 1 2

[洛谷P2774] 方格取数问题

题意 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. 想法 我们将问题转化为:一开始所有格子都选,之后去掉价值和最少的一些格子使剩下的格子合法. 将方格黑白染色,白格子连向S,黑格子连向T,边权为这个格子的值(也就是说将格子转移到边上). 相邻的黑白格子间连INF的边.(这样每条从S到T的路径都为 S->白格子->黑格子->T , 这两个格子不能同时选,S->白格子 与 黑格子->T 间必

洛谷 P1004 方格取数 【多线程DP/四维DP/】

题目描述(https://www.luogu.org/problemnew/show/1004) 设有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 某人

【动态规划】洛谷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点出发,可以向下行走,也可以向右走,直到到达右下角的B 点.在走过的路上

洛谷[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点出发,可以向下行走,也可以向右走,直到到达右下角的B 点.在走过的路上

洛谷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点出发,可以向下行走,也可以向右走,直到到达右下角的B 点.在走过的路上

[洛谷P2045]方格取数加强版

题目大意:有一个n*n的矩阵,每个格子有一个非负整数,规定一个人从(1,1)开始,只能往右或下走,走到(n,n)为止,并把沿途的数取走,取走后数变为0.这个人共取n次,求取得的数的最大总和. 解题思路:由于取多少次不确定,所以不能用dp. 我们发现,一个格子只能从左边或上面走来,且数只能取到一次,那么我们可以把此题转化为最大费用最大流问题.首先拆点,将一个点拆成x和y,然后从x到y连一条容量为1,流量为x(x为这格的数)的边,然后再连一条容量为inf,费用为0的边,这样即可保证一个点可以走多次,

dp+高精度(洛谷1005 矩阵取数游戏NOIP 2007 提高第三题)

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入格式: 输入