题解 P3956 【棋盘】

Garrison

2019-08-20 21:53:58

Solution

这道题有这么多人发题解啊,我也来凑一凑热闹。 很明显,一个普通的BFS ``` int x,y,z; scanf("%d%d",&n,&ge); for(int i=1;i<=ge;++i){ scanf("%d%d%d",&x,&y,&z); a[x][y]=z+1; } ``` 这一段是输入,储存他们的颜色,在这里,我将两种颜色分别用1、2表示(为了方便将没图色的用0来表示),所以颜色的地方+1。a数组存的是地图上哪里的颜色是什么样的。 ``` struct edge{ int xx,yy,money,color; bool use; friend bool operator <(const edge &xxx,const edge &yyy){ return xxx.money>yyy.money; } }; ``` 对于我这种蒟蒻来说,BFS就离不开结构体。xx、yy:表示位置,money:在这一个点用了多少钱,color:所在点颜色,use这个点的有没有放过魔法(0及没有,1及有) 结构体中最重要的就是operator重载运算符了,需注意它的用法(实测无误) ``` void BFS(){ priority_queue<edge> Q;//优先队列 edge e; //第一个点初始化 e.xx=e.yy=1,e.money=e.use=0; e.color=a[1][1]; Q.push(e); b[1][1]=1; while(!Q.empty()){ edge t; t=Q.top();Q.pop(); for(int i=0;i<4;++i){//四个方向 edge news; news.xx=t.xx+wx[i],news.yy=t.yy+wy[i]; if(news.xx<1||news.yy<1||news.xx>n||news.yy>n||b[news.xx][news.yy]) continue; news.use=!t.use;//上一格没用则这一格用,上一格用魔法则这一格不用 if(a[news.xx][news.yy]==0){//看一下这一个是不是没有颜色 //如果没有颜色 if(news.use)//如果这一格用魔法 news.money=t.money+2,news.color=t.color,news.use=1; else continue;//不能用魔法,跳过。 } else{ //有颜色 if(news.use) news.use=0;//如果这一格要用魔法,则没必要用(反正有颜色了) if(a[news.xx][news.yy]==t.color)//颜色相同不要钱 news.money=t.money,news.color=a[news.xx][news.yy]; else//不相同要钱 news.money=t.money+1,news.color=a[news.xx][news.yy]; } b[news.xx][news.yy]=1;//走过了不能走 if(news.xx==n&&news.yy==n){//到达 printf("%d\n",news.money); return; } Q.push(news);//入队 } } printf("-1\n"); } ``` 这一段代码就是核心部分,四个方向分别走,b数组存有没有到过。(其它我已p了注释,请诸位dalao自行审阅) # CODE ``` #include<bits/stdc++.h> using namespace std; #define N 105 int a[N][N],n,ge; const int wx[5]={0,0,1,-1}; const int wy[5]={1,-1,0,0}; bool b[N][N]; struct edge{ int xx,yy,money,color; bool use; friend bool operator <(const edge &xxx,const edge &yyy){ return xxx.money>yyy.money; } }; void BFS(){ priority_queue<edge> Q; edge e; e.xx=e.yy=1,e.money=e.use=0; e.color=a[1][1]; Q.push(e); b[1][1]=1; while(!Q.empty()){ edge t; t=Q.top();Q.pop(); for(int i=0;i<4;++i){ edge news; news.xx=t.xx+wx[i],news.yy=t.yy+wy[i]; if(news.xx<1||news.yy<1||news.xx>n||news.yy>n||b[news.xx][news.yy]) continue; news.use=!t.use; if(a[news.xx][news.yy]==0){ if(news.use) news.money=t.money+2,news.color=t.color,news.use=1; else continue; } else{ if(news.use) news.use=0; if(a[news.xx][news.yy]==t.color) news.money=t.money,news.color=a[news.xx][news.yy]; else news.money=t.money+1,news.color=a[news.xx][news.yy]; } b[news.xx][news.yy]=1; if(news.xx==n&&news.yy==n){ printf("%d\n",news.money); return; } Q.push(news); } } printf("-1\n"); } int main(){ int x,y,z; scanf("%d%d",&n,&ge); for(int i=1;i<=ge;++i){ scanf("%d%d%d",&x,&y,&z); a[x][y]=z+1; } BFS(); return 0; } ``` 但是这样就真的可以了吗?如果你和上面的程序几乎一样,你就只有95分。 为什么?因为漏了起点是重点的情况,所以要加上一段: ``` if(n==1){ printf("0\n"); return 0; } ``` 谢谢