信息战(九)——水淹七军——南阳1321

题目:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1321

过程:WA了好多次,错误原因:

1.初始化数组record[]操作:memset(record,0,sizeof(record)),放错了位置,每一个放水点,就是重新搜索一次,初始化应该dsf放在之前。一开始只我放在了一组数据开始之前
2.在一个放水点里,递归调用,走过的位置标记,但是不需要及时还原,会导致runtime error,超时。

思路:跟迷宫问题大同小异了从放水点深度搜索,每一个位置有四个方向可以走(四种选择),要注意的是可以行走的条件,只要放水点的位置比当前准备走的位置高,就可以淹没当前点,继续遍历搜索,遍历结束 发现还没有淹没司令部,重新搜索下一个放水点,注意在这之前要初始化标记数组(标记是否走过,避免重复行走)。若搜索到了,下面的放水点就不用搜索了。(大神说,水淹没的地方,都变成放水点的高度,搜索的过程中及时更新a[][]地图中点的高度,这一步确实节省了时间,但是不需要。因为后一个放水点如果比前一个高,那更新就做了无用功了,不论如何都要经过他;若放水点比前一个放水点低,如果不更新,会走的时间长一点。嗯....好吧,其实还是大神想的周到,更新总是好的)。

dfs()函数依然分为两部分,if部分(结束 标志),else部分(每一次,每一层的选择),dfs的参数,写变化的部分(到了第几层,第几个位置)。

代码:

 1 #include<stdio.h>
 2 #include<memory.h>
 3 int a[205][205],flag,m,n,m1,n1,I,J,D[4][2]={-1,0,1,0,0,-1,0,1},record[205][205];//D四个方向,(m1,n1)司令部的位置,record[]记录是否走过
 4 void dfs(int x,int y){
 5     int nx,ny;
 6     record[x][y]=1;//表遍历过(避免重复走)
 7     //if部分(如果淹到了司令部)
 8     if(x==m1&&y==n1){//水淹到了司令部
 9         flag=1;//淹没了
10         return;
11     }
12     //else部分(选择,四个方向)
13     else{
14     for(int i=0;i<4;i++)//四个方向
15     {
16             nx=x+D[i][0];//四个方向遍历
17             ny=y+D[i][1];
18             if(record[nx][ny]==0&&a[I][J]>=a[nx][ny]&&nx>0&&nx<=m&&ny>0&&ny<=n) //若下一个方向上的点 没有走过,放水点比当前点的高度高或相等 ,水流可经过,继续遍历
19             {
20                 dfs(nx,ny);
21                 //record[x][y]=0;//不必还原,还原只会走重复的路,一直循环,导致超时
22             }
23     }
24     }
25 }
26 int main(){
27     int K,N,i,j;
28    freopen("1.txt","r",stdin);
29     scanf("%d",&K);//K组数据
30     //地图(各点的高度)
31     while(K--){
32     flag=0;//初始化
33     scanf("%d %d",&m,&n);
34     memset(record,0,sizeof(record));
35     for(i=1; i<=m; i++)//从1开始存,与位置信息相对应
36     {
37         for(j=1; j<=n; j++)
38         {
39             scanf("%d",&a[i][j]);
40         }
41     }
42     scanf("%d %d",&m1,&n1);//指挥部位置
43     scanf("%d",&N);
44     for(i=0;i<N;i++){
45         scanf("%d %d",&I,&J);//放水的位置
46     if(!flag){//没被淹没,看下一个放水点
47     memset(record,0,sizeof(record));
48     dfs(I,J);//调用dfs,判断是否可以到 指挥部
49     }
50     }
51     if(flag)
52          printf("Yes\n");
53     else
54         printf("No\n");
55     }
56 return 0;
57 }

 

转载于:https://www.cnblogs.com/li-yaoyao/p/9498377.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值