标签:比较 连续 就是 head pop bfs ace idt copy
原题:
5 7
1 1 0
1 2 0
2 2 1
3 3 1
3 4 0
4 4 1
5 5 0
8
~~本蒟蒻第一次写题解,写的不好多多包涵~~
这是一道很明显的搜索题,最近几天在练BFS的题目,所以讲讲BFS解题思路,大佬勿喷
题意:
在一个m*m的棋盘中,从(1,1)出发到(m,m),上下左右移动,移动到同色格子不需要代价,移动到不同色格子需要代价为1,不能移动到无色格子但可以花费代价2将无色格子变为有色格子,**不能从无色格子移动到另一无色格子**
首先考虑从一个格子走到另一个格子有哪些情况
(方便起见将红色设为1,黄色设为2,无色设为0):
1. 从有色格子走到同一有色格子(1->1或2->2)
2. 从有色格子走到不同色的有色格子(1->2或2->1)
3. 从有色格子走到无色格子(此时需要使用魔法)(1->0或2->0)
4. 从施了魔法的无色格子移动到有色格子(还需考虑魔法将无色格子变成了什么颜色)(0->1或0->2)
接着考虑搜索到一个可走的点时需要将哪些元素压入队列,用一个结构体捆绑
1 struct node 2 { 3 int x,y,c,s,p; 4 }now;
其中x,y表示加入队列的点的坐标(x,y),c记录该点原本的颜色,s记录该点施了魔法后的颜色(若该点原本有色则s仍为原本的颜色),p记录目前所需的代价。
因为本题需要的是代价最小而不是步数,所以最先搜索到的点不一定是代价最小的点,再建一个v数组统计所有可能的代价。
套入BFS的模板,代码如下:
1 #include<iostream> 2 #include<stdio.h> 3 #include<queue> 4 using namespace std; 5 int n,m,ans,tot,mark[1005][1005],map[1005][1005],v[5005]; 6 //tot统计所有可能的代价 7 //mark记录到各个点的最小代价 8 //map记录棋盘初始状况 9 //v记录到达终点的所有可能的代价 10 int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; 11 //用dx,dy两个数组控制移动方向 12 struct node 13 { 14 int x,y,c,s,p; 15 }now; 16 queue<node> q;//STL库自带的队列 17 //听说速度会比手打队列慢一点,但应该关系不大 18 void bfs(int x,int y) 19 { 20 mark[x][y]=0;//起点不需要代价 21 q.push({x,y,map[x][y],map[x][y],0}); 22 while(!q.empty()) 23 { 24 now=q.front(); 25 q.pop();//出队 26 x=now.x,y=now.y; 27 int c=now.c,p=now.p,s=now.s; 28 if(x==m && y==m) v[++tot]=p;//找到一个解就存入v数组 29 for(int i=0;i<4;i++) 30 { 31 int tx=x+dx[i],ty=y+dy[i]; 32 if(tx>=1 && tx<=m && ty>=1 && ty<=m) 33 {//判断是否越界 34 if(map[x][y]!=0 && map[x][y]==map[tx][ty] && mark[tx][ty]>p) 35 { 36 mark[tx][ty]=p;//如果可以得到更小代价就更新,下同 37 q.push({tx,ty,map[tx][ty],map[tx][ty],p});//入队 38 } 39 //第一种情况 40 else if(map[x][y]!=0 && map[tx][ty]!=0 && map[x][y]!=map[tx][ty] && mark[tx][ty]>p+1) 41 { 42 mark[tx][ty]=p+1; 43 q.push({tx,ty,map[tx][ty],map[tx][ty],p+1}); 44 } 45 //第二种情况 46 else if(map[x][y]!=0 && map[tx][ty]==0 && mark[tx][ty]>p+2) 47 { 48 mark[tx][ty]=p+2; 49 q.push({tx,ty,map[tx][ty],map[x][y],p+2}); 50 //注意,这种情况需要使用一次魔法,此时s记录为未移动前的格子的颜色 51 } 52 //第三种情况 53 else if(map[x][y]==0 && map[tx][ty]==s && mark[tx][ty]>p) 54 { 55 mark[tx][ty]=p; 56 q.push({tx,ty,mark[tx][ty],mark[tx][ty],p}); 57 } 58 //第四种情况(1) 59 else if(map[x][y]==0 && map[tx][ty] && map[tx][ty]!=s && mark[tx][ty]>p+1) 60 { 61 mark[tx][ty]=p+1; 62 q.push({tx,ty,mark[tx][ty],mark[tx][ty],p+1}); 63 } 64 //第四种情况(2) 65 //如果这几种情况都不符合,只剩下从无色格子到无色格子一种可能,不需考虑 66 } 67 } 68 } 69 return; 70 } 71 int main() 72 { 73 scanf("%d %d",&m,&n); 74 for(int i=1;i<=m;i++) 75 for(int j=1;j<=m;j++) mark[i][j]=0x7fffffff; 76 //将到达各个点的最小代价初始化为无穷大(0x7fffffff) 77 for(int i=1;i<=n;i++) 78 { 79 int a,b,cl; 80 scanf("%d %d %d",&a,&b,&cl); 81 map[a][b]=cl+1;//将红色记为1,黄色记为2,无色则为0 82 } 83 bfs(1,1); 84 if(!tot) { printf("-1"); return 0; }//如果没有解,输出-1 85 ans=v[1]; 86 for(int i=2;i<=tot;i++) ans=min(ans,v[i]); 87 //比较并求出最小代价 88 printf("%d",ans); 89 return 0; 90 }
标签:比较 连续 就是 head pop bfs ace idt copy
原文地址:https://www.cnblogs.com/leaf-2234/p/13307471.html