现在主要讲讲建边的问题,许多图难就难在建边上,建完边后就是简单的裸题什么之类的,游戏机器人就是这样一道题。
游戏机器人
时间限制: 1 Sec 内存限制: 128 MB提交: 77 解决: 43
[提交][状态][讨论版]
题目描述
让我们来玩一个机器人游戏,游戏在一个长方形网格上进行,机器人最初被安放在长方形网格的左上角且面朝东,而游戏的目标就是使到达右下网格。
机器人可以执行以下5种操作:
"Straight": 保持机器人当前的方向,并前进一格。
"Right": 右转90度,并前进一格
"Back": 转180度,并前进一格
"Left": 左转90度,并前进一格
"Halt": 停在原地,并结束游戏。
机器人可以经过同一个方块多次。如果你在游戏过程中,让机器人走出边界或者在到达目标之前执行了“Halt”指令,你都将失败。
现在你的任务是计算最小的代价,使机器人从起点到达终点。
输入
文件开始两个整数w,h,表示列和行数(2 ≤ h ≤ 30 ,2 ≤ w ≤ 30)
接下来共h行w列整数
最后4个整数c0 c1 c2 c3。
格式如下:
w h
s(1,1) ... s(1,w)
s(2,1) ... s(2,w)
...
s(h,1) ... s(h,w)
c0 c1 c2 c3
矩阵中数字代表的含义如下:
0: "Straight"
1: "Right"
2: "Back"
3: "Left"
4: "Halt"
保证“Halt”命令将出现在目标位置,但也可能出现在矩阵中某个方格中。
最后4个数字c0, c1, c2, 和c3, 分别表示你使用"Straight", "Right", "Back", and "Left" 命令的代价,其值在1~9之间。
输出
输出机器人从起点到终点的最小代价。
样例输入
样例输出
提示
30%数据w,h<10
100%数据w,h<=30
裂点+Dijkstra ,建图其实一般人都看的出来,但是想着想着就是十分困难的,然后就Give up!了,像这种网格图,Spfa貌似没什么优势,但是点又比较多,一格裂成4个点,但是数据范围比较小,时间复杂度还是可以的。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<queue> 7 using namespace std; 8 9 const int WW=37,HH=37; 10 typedef pair<int,int> fzy; 11 12 int n,m,S,T; 13 int a[WW][HH],b[5]; 14 int dis[WW*HH*5],cnt,head[WW*HH*5],next[WW*HH*HH],val[WW*HH*HH],rea[WW*HH*HH]; 15 struct cmp 16 { 17 bool operator()(fzy a,fzy b) 18 {return a.first>b.first;} 19 }; 20 priority_queue<fzy,vector<fzy>,cmp>q; 21 22 void add(int u,int v,int fee) 23 { 24 cnt++; 25 next[cnt]=head[u]; 26 head[u]=cnt; 27 rea[cnt]=v; 28 val[cnt]=fee; 29 } 30 int edg(int x,int y) 31 { 32 if (x==y) return 0; 33 return b[y]; 34 } 35 void make(int i,int j) 36 { 37 int u=((i-1)*m+j-1)*4+1; 38 if (j+1<=m) add(u,((i-1)*m+j)*4+1,edg(a[i][j],0)); 39 if (i+1<=n) add(u,(i*m+j-1)*4+2,edg(a[i][j],1)); 40 if (j-1>=1) add(u,((i-1)*m+j-2)*4+3,edg(a[i][j],2)); 41 if (i-1>=1) add(u,((i-2)*m+j-1)*4+4,edg(a[i][j],3)); 42 43 u=((i-1)*m+j-1)*4+2; 44 if (i+1<=n) add(u,(i*m+j-1)*4+2,edg(a[i][j],0)); 45 if (j-1>=1) add(u,((i-1)*m+j-2)*4+3,edg(a[i][j],1)); 46 if (i-1>=1) add(u,((i-2)*m+j-1)*4+4,edg(a[i][j],2)); 47 if (j+1<=m) add(u,((i-1)*m+j)*4+1,edg(a[i][j],3)); 48 49 u=((i-1)*m+j-1)*4+3; 50 if (j-1>=1) add(u,((i-1)*m+j-2)*4+3,edg(a[i][j],0)); 51 if (i-1>=1) add(u,((i-2)*m+j-1)*4+4,edg(a[i][j],1)); 52 if (j+1<=m) add(u,((i-1)*m+j)*4+1,edg(a[i][j],2)); 53 if (i+1<=n) add(u,(i*m+j-1)*4+2,edg(a[i][j],3)); 54 55 u=((i-1)*m+j-1)*4+4; 56 if (i-1>=1) add(u,((i-2)*m+j-1)*4+4,edg(a[i][j],0)); 57 if (j+1<=m) add(u,((i-1)*m+j)*4+1,edg(a[i][j],1)); 58 if (i+1<=n) add(u,(i*m+j-1)*4+2,edg(a[i][j],2)); 59 if (j-1>=1) add(u,((i-1)*m+j-2)*4+3,edg(a[i][j],3)); 60 } 61 void Dijkstra() 62 { 63 bool boo[4007]; 64 memset(boo,0,sizeof(boo)); 65 memset(dis,100,sizeof(dis)); 66 dis[S]=0; 67 q.push(make_pair(0,S)); 68 while (!q.empty()) 69 { 70 fzy now=q.top(); 71 q.pop(); 72 if (boo[now.second]) continue; 73 boo[now.second]=1; 74 int u=now.second; 75 for (int i=head[u];i!=-1;i=next[i]) 76 { 77 int v=rea[i],fee=val[i]; 78 if (dis[u]+fee<dis[v]&&!boo[v]) 79 { 80 dis[v]=dis[u]+fee; 81 q.push(make_pair(dis[v],v)); 82 } 83 } 84 } 85 printf("%d ",dis[T]); 86 } 87 int main() 88 { 89 cnt=0; 90 memset(head,-1,sizeof(head)); 91 scanf("%d%d",&m,&n); 92 for (int i=1;i<=n;i++) 93 for (int j=1;j<=m;j++) 94 scanf("%d",&a[i][j]); 95 a[n][m]=-1; 96 for (int i=0;i<=3;i++) 97 scanf("%d",&b[i]); 98 for (int i=1;i<=n;i++) 99 for (int j=1;j<=m;j++) 100 make(i,j); 101 102 S=n*m*4+1,T=n*m*4+2; 103 add(S,1,0); 104 add((n*m-1)*4+1,T,0),add((n*m-1)*4+2,T,0),add((n*m-1)*4+3,T,0),add((n*m-1)*4+4,T,0); 105 Dijkstra(); 106 }