仅仅做出了1009(hdu-4308),广搜,搜到第一个P的时候将左右P都入队列并标记,再继续搜下去,搜到C即得出结果。
View Code
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; #define V 5010 char map[V][V]; bool vis[V][V]; int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}}; struct Node { int x,y; long long step; }q[V]; int r,c,cost; long long bfs(int xx,int yy) { vis[xx][yy]=1; int head=0,tail=0; q[tail].x=xx; q[tail].y=yy; q[tail++].step=0; while(head<tail) { xx=q[head].x; yy=q[head].y; long long ss=q[head++].step; for(int i=0;i<4;i++) { int xxx=xx+dir[i][0]; int yyy=yy+dir[i][1]; if(vis[xxx][yyy]==0 && map[xxx][yyy]!='#' && xxx>=0 && xxx<r && yyy>=0 && yyy<c) { vis[xxx][yyy]=1; q[tail].x=xxx; q[tail].y=yyy; if(map[xxx][yyy]=='C') { return ss; } if(map[xxx][yyy]=='*') { q[tail++].step=ss+cost; } if(map[xxx][yyy]=='P') { q[tail++].step=ss; for(int i=0;i<r;i++) { for(int j=0;j<c;j++) { if(map[i][j]=='P') { vis[i][j]=1; q[tail].x=i; q[tail].y=j; q[tail++].step=ss; } } } } } } } return -1; } int main() { long long res; while(cin >> r >> c >> cost) { for(int i=0;i<r;i++) { scanf("%s",map[i]); } memset(vis,0,sizeof(vis)); for(int i=0;i<r;i++) { for(int j=0;j<c;j++) { if(map[i][j]=='Y') { res=bfs(i,j); } } } if(res==-1) cout <<"Damn teoy!" << endl; else cout << res << endl; } return 0; }
该题还有最短路算法:
给出的地图中,Y为起点,C为终点,#点不能通过,可直接忽略。所有的P为互通的传送门,故可将所以的P看作同一个点。每个能通过的点可以向上下左右四个方向走,如果对应的方向可以通过,则连边,若要走到的点是*,则边权为通过的费用,否则边权为0。
连边后求Y到C的最短路即可。
View Code
#include <iostream> #include <stdio.h> #include <string.h> #include <queue> #include <algorithm> using namespace std; #define V 5005 #define E 200100 #define typec int int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; const typec inf=0x7FFFFFFF; typec cost[E],dist[V]; char map[V][V]; int num[V][V]; int n,m,C,s,t,cou; int e,pnt[E],nxt[E],head[V],prev[V],vis[V]; struct qnode{ int v;typec c; qnode(int vv=0,typec cc=0) :v(vv),c(cc){} bool operator<(const qnode& r) const {return c>r.c;} }; void dijkstra(int n,const int src){ qnode mv; int i,j,k,pre; priority_queue<qnode> que; vis[src]=1;dist[src]=0; que.push(qnode(src,0)); for(pre=src,i=1;i<n;i++){ for(j=head[pre];j!=-1;j=nxt[j]){ k=pnt[j]; if(vis[k]==0 && dist[pre]+cost[j]<dist[k]){ dist[k] = dist[pre]+cost[j]; que.push(qnode(pnt[j],dist[k])); prev[k]=pre; } } while(!que.empty() && vis[que.top().v]==1) que.pop(); if(que.empty()) break; mv = que.top();que.pop(); vis[pre=mv.v]=1; } } inline void addedge(int u,int v,typec c){ pnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=e++; } void init(){ int i,u,v;typec c; e=0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(prev,-1,sizeof(prev)); for(i=0;i<=n*m+1;i++) dist[i]=inf; cou=1; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ num[i][j]=cou++; } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(map[i][j]=='Y'){ s=num[i][j]; } if(map[i][j]=='C'){ t=num[i][j]; } if(map[i][j]=='#') continue; else if(map[i][j]=='P'){ cou--; for(int k=0;k<4;k++){ int ii=i+dir[k][0]; int jj=j+dir[k][1]; if(!(ii>=0 && ii<n && jj>=0 && jj<m)) continue; if(map[ii][jj]=='*'){ addedge(0,num[ii][jj],C); } else if(map[ii][jj]=='C'){ addedge(0,num[ii][jj],0); } else if(map[ii][jj]=='P'){ addedge(0,0,0); } } } else{ for(int k=0;k<4;k++){ int ii=i+dir[k][0]; int jj=j+dir[k][1]; if(!(ii>=0 && ii<n && jj>=0 && jj<m)) continue; if(map[ii][jj]=='*'){ addedge(num[i][j],num[ii][jj],C); } else if(map[ii][jj]=='C'){ addedge(num[i][j],num[ii][jj],0); } else if(map[ii][jj]=='P'){ addedge(num[i][j],0,0); } } } } } } int main(){ //freopen("in.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&C)!=EOF){ for(int i=0;i<n;i++){ scanf("%s",map[i]); } init(); dijkstra(n*m+1,s); if(dist[t]==inf) printf("Damn teoy!\n"); else printf("%d\n",dist[t]); } return 0; }
未加边界处理,WA了几次,o(╯□╰)o,以后做棋盘上的题一定一定要注意边界处理。
在下一场比赛到来之前,要懂得:
4.2-SAT过1007(8.20)
6.最大流过1010(8.21)
3.生成树计数过1006(8.22)
2.线段树过1003(8.23)
5.最短路过1009(8.24)
1.KMP过1001(8.25)