洛谷提高组P1004+1006

[NOIP2000 提高组] 方格取数 - 洛谷

题意:有N×N 的方格图,将其中的某些方格中填入正整数,而其他的方格放入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条这样的路径,使得取得的数之和为最大。

分析:动态规划,4维数组分别记录两条线路的位置坐标即可。

唯一的不足就是用了4重循环,题干给的数据范围比较小,其实应该更优化一点,暂时还不会。

#include<iostream>
using namespace std;
int a[10][10];
int f[10][10][10][10];
int max1(int a,int b,int c,int d)
{
    int m=max(a,b);
    m=max(m,c);
    m=max(m,d);
    return m;
}
int main()
{
    int n,x,y,z;
    cin>>n;
    for(int i=0; i<=n; i++)
        for(int j=0; j<=n; j++)
            a[i][j]=0;
    cin>>x>>y>>z;
    while(x+y+z!=0)
    {
        a[x][y]=z;
        cin>>x>>y>>z;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int h=1;h<=n;h++)
            {
                for(int k=1;k<=n;k++)
                {
                    if(i!=h&&j!=k)
                    {
                        f[i][j][h][k]=max(f[i][j][h][k],(max1(f[i-1][j][h-1][k],f[i-1][j][h][k-1],f[i][j-1][h-1][k],f[i][j-1][h][k-1])+a[i][j]+a[h][k]));
                    }
                    else f[i][j][h][k]=max(f[i][j][h][k],(max1(f[i-1][j][h-1][k],f[i-1][j][h][k-1],f[i][j-1][h-1][k],f[i][j-1][h][k-1])+a[i][j]));
                }
            }
        }
    }
    cout<<f[n][n][n][n]<<endl;
}

[NOIP2008 提高组] 传纸条 - 洛谷

分析:和方格取数是一种题型,改一下输入条件和范围就可以了。

(看题干想偏了,想了两种方法,一种是两个二维dp数组,一个记录从小渊到小轩的最大值,路过点标0,然后再记录从小轩回到小渊的最大值,忽略了有去无回的情况,所以不对;另一种四维dp数组,和方格取数一样,不过一个起点在[1][1]另一个在[m][n],实际上还是忽略了有去无回的情况。)

#include<iostream>
using namespace std;
int a[51][51];
int f[51][51][51][51];
int max1(int a,int b,int c,int d)
{
    int m=max(a,b);
    m=max(m,c);
    m=max(m,d);
    return m;
}
int maxx=0;
int main()
{
    int m,n;
    cin>>m>>n;
    for(int i=0; i<=m; i++)
        for(int j=0; j<=n; j++)
            a[i][j]=0;
    for(int i=1; i<=m; i++)
        for(int j=1; j<=n; j++)
            cin>>a[i][j];
    for(int i=1; i<=m; i++)
    {
        for(int j=1; j<=n; j++)
        {
            for(int h=1; h<=m; h++)//必须从1开始
            {
                for(int k=1; k<=n; k++)
                {
                    if(i!=h&&j!=k)
                    {
                        f[i][j][h][k]=max(f[i][j][h][k],(max1(f[i-1][j][h-1][k],f[i-1][j][h][k-1],f[i][j-1][h-1][k],f[i][j-1][h][k-1])+a[i][j]+a[h][k]));
                    }
                    else f[i][j][h][k]=max(f[i][j][h][k],(max1(f[i-1][j][h-1][k],f[i-1][j][h][k-1],f[i][j-1][h-1][k],f[i][j-1][h][k-1])+a[i][j]));
                }
            }
        }
    }
    cout<<f[m][n][m][n]<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值