2017.1.13【初中部 GDKOI】模拟赛B组 我要的幸福 题解

原题 :

http://172.16.0.132/senior/#contest/show/1894/1

题目描述:

幸福/我要的幸福/渐渐清楚/梦想/理想/幻想/狂想/妄想/我只想坚持每一步/该走的方向/就算一路上/偶尔会沮丧/生活是自己/选择的衣裳/幸福/我要的幸福/没有束缚/幸福/我要的幸福/在不远处

Zyh相信自己想要的幸福在不远处。然而,zyh想要得到这幸福,还需要很长的一段路。Zyh坚持认为整个人生可以抽象为一个n*m的棋盘。左上角的格子为(1,1),右下角的格子为(n,m)。整个棋盘上的格子都有不同的事件,因为生活的多姿多彩,事件的权值Aij都两两不同。不幸的是,在整个人生中有若干个极其黑暗的事件,它们的权值Aij=0。更进一步说,对于Aij>0的事件,权值两两不同。
Zyh站在人生的起点(1,1),他想要走向人生的巅峰(n,m)。Zyh认为人只能前进,即若Zyh站在(a,b),他只能走向(a,b+1)或者(a+1,b)。并且Zyh认为黑暗的事件是绝对不可以触碰的,因为一旦经历就会坠入万丈深渊。Zyh会将自己所经历的事件的权值依次写出,形成一个n+m-1的序列。Zyh想知道其中字典序最小的序列是什么。若是人生过于艰难,没有一个合法序列,就输出”Oh,the life is too difficult!”,不包含引号。

输入:

输入的第一行是两个正整数n和m。接着是n行m列的人生棋盘。

输出:

输入只有一列,如果存在合法序列,则为n+m-1个用一个空格隔开的权值。否则就输出Oh,the life is too difficult!

样例输入:

输入1:
3 3
1 3 4
7 9 0
5 6 8
输入2:
2 3
1 0 3
0 4 5

样例输出:

输出1:
1 3 9 6 8
输出2:
Oh,the life is too difficult!

数据范围限制:

对于20%的数据 n<10 m<10
对于60%的数据 n<=300 m<=300
对于100%的数据 n<=1000 m<=1000 Aij<=1e9

分析:

对于每一个矩阵,我们可以用dfs进行宽搜,但很遗憾,只能拿到一点可怜的分;
我们可以加剪枝:
剪枝1:对于这里写图片描述,我们可以用贪心策略:因为只能往下或右走并且要字典序最小,所以我们在二者中找一个较小的数搜,知道不行了再往回搜,但这只能拿60分;
剪枝2:对于这里写图片描述,我们可以进行记忆化搜索,路径“1 3 9”,我们把“9”的坐标bz[2,2]为false,这样在下次搜到“9”时,例如“1 7 9”时,就不必再找了,不必担心新找的路会比原来的路小,因为剪枝1已经解决了这个问题;
两个剪枝一起用,双管齐下,AC100;

实现:

#include<cstdio>  
#include<iostream>  
using namespace std;  

int n,m,t,w,l,r,len,a[1005][1005],x[1000005],y[1000005],f[1000005],p[1005][1005],ans[2005];  
int main()  
{  
    scanf("%d%d",&n,&m); 
    for(int i=1;i<=n;i++)   
    for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);  
    t=0;w=1;  
    x[1]=1;y[1]=1;p[1][1]=1;  
    while(t<w)   
    {  
        t++;  
        if(x[t]==n&&y[t]==m) break;  
        l=x[t]; r=y[t];  
        if(a[l+1][r]<a[l][r+1])   
        {  
            if(a[l+1][r]>0&&p[l+1][r]==0)    
            {  
                w++;  
                x[w]=l+1;  
                y[w]=r;  
                f[w]=t;  
                p[l+1][r]=1;  
            }  
            if(a[l][r+1]>0&&p[l][r+1]==0)   
            {  
                w++;  
                x[w]=l;  
                y[w]=r+1;  
                f[w]=t;  
                p[l][r+1]=1;  
            }  
        }  
        else  
        {  
            if(a[l][r+1]>0&&p[l][r+1]==0)   
            {  
                w++;  
                x[w]=l;  
                y[w]=r+1;  
                f[w]=t;  
                p[l][r+1]=1;  
            }  
            if(a[l+1][r]>0&&p[l+1][r]==0)    
            {  
                w++;  
                x[w]=l+1;  
                y[w]=r;  
                f[w]=t;  
                p[l+1][r]=1;  
            }  
        }  
    }
    while(f[t]!=0)   
    {  
        len++;  
        ans[len]=a[x[t]][y[t]];  
        t=f[t];       
    } 
    if(a[1][1]==0||len!=n+m-2)   
    { 
        printf("Oh,the life is too difficult!");
        return 0;  
    }  
    len++;  
    ans[len]=a[1][1];  
    for(int i=len;i>1;i--) printf("%d ",ans[i]);  
    printf("%d",ans[1]); 
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值