洛谷P1004 [NOIP2000 提高组] 方格取数c++题解

题目背景

NOIP 2000 提高组 T4

题目描述

设有 N×N 的方格图 (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0。如下图所示(见样例):

某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。
此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。

输入格式

输入的第一行为一个整数 N(表示 N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 表示输入结束。

输出格式

只需输出一个整数,表示 22条路径上取得的最大的和。

输入输出样例

输入 #1

8
2 3 13
2 6  6
3 5  7
4 4 14
5 2 21
5 6  4
6 3 15
7 2 14
0 0  0

输出 #1

67

说明/提示

数据范围:1≤N≤9。

AC代码:

那么上代码!!!

//方格取数~深搜  ~( ̄▽ ̄~)(~ ̄▽ ̄)~
#include<bits/stdc++.h>//万能头!!!!I love you.
    using namespace std;
    int N=0;
    int s[15][15],f[11][11][11][11];
int dfs(int x,int y,int x2,int y2)//两种方案同时执行,表示当第一种方案走到x,y,第二种方案走到x2,y2时到终点取得的最大数 
{
    if (f[x][y][x2][y2]!=-1) return f[x][y][x2][y2];//如果这种情况已经被记录过了,直接返回,节省时间 
    if (x==N&&y==N&&x2==N&&y2==N) return 0;//如果两种方案都走到了终点,返回结束 
    int M=0;
    //如果两种方案都不在最后一列,就都往下走,统计取得的数,如果有重复,就减去一部分 
    if (x<N&&x2<N) M=max(M,dfs(x+1,y,x2+1,y2)+s[x+1][y]+s[x2+1][y2]-s[x+1][y]*(x+1==x2+1&&y==y2));
    //如果第一种方案不在最后一行,第二种方案不在最后一列,第一种就向下走,第二种就向右走, 
    //统计取得的数,如果有重复,就减去一部分
    if (x<N&&y2<N) M=max(M,dfs(x+1,y,x2,y2+1)+s[x+1][y]+s[x2][y2+1]-s[x+1][y]*(x+1==x2&&y==y2+1));
    //如果第一种方案不在最后一列,第二种方案不在最后一行,第一种就向右走,第二种就向下走, 
    //统计取得的数,如果有重复,就减去一部分
    if (y<N&&x2<N) M=max(M,dfs(x,y+1,x2+1,y2)+s[x][y+1]+s[x2+1][y2]-s[x][y+1]*(x==x2+1&&y+1==y2));
    //如果第一种方案和第二种方案都不在最后一列,就都向右走,统计取得的数,如果有重复,就减去一部分
    if (y<N&&y2<N) M=max(M,dfs(x,y+1,x2,y2+1)+s[x][y+1]+s[x2][y2+1]-s[x][y+1]*(x==x2&&y+1==y2+1));
    //对最后那个 s[x][y+1]*(x==x2&&y+1==y2+1))的解释:这个是用来判断两种方案是不是走到了同一格的
    //如果是真,就返回1,否则返回0,如果是1的话,理所当然的可以减去s[x][y+1]*1,否则减去s[x][y+1]*0相当于
    //不减,写得有点精简,省了4个if,见谅哈~ 
    f[x][y][x2][y2]=M;//记录这种情况 
    return M;//返回最大值 
}
int main()
{
    cin>>N;
    //将记录数组初始化成-1,因为可能出现取的数为0的情况,如果直接判断f[x][y][x2][y2]!=0(见dfs第一行)
    //可能出现死循环而导致超时,细节问题 
    for(int a=0;a<=N;a++)
      for(int b=0;b<=N;b++)
        for(int c=0;c<=N;c++)
          for(int d=0;d<=N;d++) f[a][b][c][d]=-1;
    for(;;)//读入 
    {
        int t1=0,t2=0,t3=0;
        cin>>t1>>t2>>t3;
        if(t1==0&&t2==0&&t3==0) break;
        s[t1][t2]=t3;
    }
    cout<<dfs(1,1,1,1)+s[1][1];//输出,因为dfs中没有考虑第一格,即s[1][1],所以最后要加一下 
    return 0;
}

那么!你——学会了吗?

管你学没学会,刷AC就完了!!!!!!!!!

QVQ

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值