信息战(九)——水淹七军——南阳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 }