算法_棋盘型高维动态规划

一. P1006 传纸条

P1006 传纸条

题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个 m 行 n
列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标
(1,1),小轩坐在矩阵的右下角,坐标 (m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用 0 表示),可以用一个 [0,100]内的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度之和最大。现在,请你帮助小渊和小轩找到这样的两条路径。
输入格式 第一行有两个用空格隔开的整数 m 和 n,表示班里有 m 行 n 列。接下来的 m 行是一个 m×n 的矩阵,矩阵中第 i 行 j 列的整数表示坐在第 i 行 j 列的学生的好心程度。每行的 n 个整数之间用空格隔开。
输出格式 输出文件共一行一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

输入:
3 3
0 3 9
2 8 5
5 7 0
输出:
34

思路:要求传纸条传过去再传过来,所以就两个人一块走
用三维DP来做。f[p][i][j]中,p代表两人走到步数,i是第一个人现在的行数,j是第二个人现在所在的行数

#include<bits/stdc++.h>
using namespace std;
const int maxn=120;
typedef long long ll;
ll a[maxn][maxn],n,m,f[maxn][maxn][maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>a[i][j];
    f[1][1][1]=a[1][1];
    for(int p=2;p<=n+m-1;p++)
        for(int i=1;i<=n&&i<=p;i++)
        for(int j=1;j<=n&&j<=p;j++)
        {
            if(i==1&&j==1)continue;
            f[p][i][j]=max(max(f[p-1][i][j],f[p-1][i-1][j-1]),max(f[p-1][i][j-1],f[p-1][i-1][j]));//代表四个过来的方向——右右,下下,上右,右上,取最大值赋给f[p][i][j];
            f[p][i][j]+=(i==j)?a[i][p-i+1]:a[i][p-i+1]+a[j][p-j+1];
        }
    cout<<f[n+m-1][n][n]<<endl;
    return 0;
}

没懂?没懂看这个

题2

题目描述
设有 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 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0 )。此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。
输入格式
输入的第一行为一个整数 N(表示 N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
输出格式
只需输出一个整数,表示 2 条路径上取得的最大的和。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e2;
const int mod=1e9+7;
int mp[maxn][maxn],f[maxn][maxn][maxn][maxn],a,b,c,d;
int n;
int main()
{
    cin>>n;
    while(cin>>a>>b>>c)
    {
        if(a==0&&b==0&&c==0)break;
        mp[a][b]=c;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        for(int l=1;l<=n;l++)
        {
            f[i][j][k][l]=max(max(f[i-1][j][k-1][l],f[i][j-1][k][l-1]),max(f[i-1][j][k][l-1],f[i][j-1][k-1][l]));
            f[i][j][k][l]+=(mp[i][j]+mp[k][l]);
            if(i==k&&j==l)f[i][j][k][l]-=mp[i][j];
        }
    cout<<f[n][n][n][n]<<endl;
    return 0;
}

与上题类似

Fillin的赚钱之路

Fillin的赚钱之路
题目描述
benTuTuT找遍了他的朋友,都没有借到钱,于是想到了Fillin,慷慨的Fillin告诉benTuTuT:“借钱是小事,但能借到多少就看你的本事了,我这里有一张地图,迷宫的每一个房间都有钱,但是你必须按照我给的规则行走,能拿到多少钱就看你自己的本事了。” 这里有一个有nm个房间的地图每个房间的编号为a[i]j代表他在第i行的第j个房间, 当benTuTuT在第i行的第j个房间时,他可以选择横着走,也可以选择竖着走 横着走时,他只能到达第i排的第j+1个房间或者是j的倍数编号的房间(不包括它本身) 竖着走时,他只能到达第i+1排房间或者是i的非倍数编号排的第j个房间(不包括它本身) 比如他在第3行第4个房间时, 他横着走可以到达:第3行的第5,8,12,16等房间 他竖着走可以到达:第4,5,7,8,10等行的第4个房间 benTuTuT最开始在a[1][1],他需要走到a[n][m]才能将钱提现 每一个房间内都有一个数字x当x为正数时benTuTuT可以获得x元,反之benTuTuT需要交给Fillin x元 benTuTuT必须进入每一个他经过的房间,并且拿走里面的钱,或者留下规定的钱(他一定会进入a[1][1]和a[n][m]) 你需要帮助benTuTuT获得尽可能给多的获得钱,并且告诉benTuTuT最多获得多少钱。
输入描述:
第一行输入一个整数t,代表有t组测试数据,对于每组测试数据,第一行输入两个整数n和m代表有n行m列个房间接下来n行,每行m个分开的整数a[i][j],代表每个房间内拥有的钱数1<=t<=101<=n,m<=1000<=a[i][j]<=1
10^6
输出描述:
对于每组测试数据,并且对于每组数据,答案占单独的一行。
思路:遍历一遍,每到一个点,就把所有能到这个点的所有路径全部比较一遍求最大值。(三维DP)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int t,n,m,a[maxn][maxn],temp,dp[maxn][maxn];
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            cin>>a[i][j],dp[i][j]=-23333333;
        dp[1][1]=a[1][1];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                temp=dp[i][j];
                for(int k=1;k<j;k++)
                    if(j%k==0||j==k+1)
                        temp=max(dp[i][k]+a[i][j],temp);
                for(int s=1;s<i;s++)
                    if(i%s!=0||i==s+1)
                        temp=max(dp[s][j]+a[i][j],temp);
                dp[i][j]=temp;
            }
        cout<<dp[n][m]<<endl;
    }
    return 0;
}


发布了40 篇原创文章 · 获赞 51 · 访问量 2515

猜你喜欢

转载自blog.csdn.net/weixin_45697774/article/details/103787873
今日推荐