游戏机器人

来源:互联网 发布:被一个人爱的感觉知乎 编辑:程序博客网 时间:2024/05/16 10:28

题目描述
让我们来玩一个机器人游戏,游戏在一个长方形网格上进行,机器人最初被安放在长方形网格的左上角且面朝东,而游戏的目标就是使到达右下网格。
这里写图片描述
机器人可以执行以下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之间。

输出
输出机器人从起点到终点的最小代价。

样例输入
8 3
0 0 0 0 0 0 0 1
2 3 0 1 4 0 0 1
3 3 0 0 0 0 0 4
9 9 1 9
样例输出
1
提示
30%数据w,h<10
100%数据w,h<=30

最短路+裂点,其实就是对每个点分裂成不同方向的四个点。
然后进行添边的分类大讨论,这部分代码重载率很高,可以用循环和子程序尽量缩短代码。

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#define ll long longusing namespace std;int n,m,x,y,t,w,id,tot,all,ans,d1,d2,d3,d4,c1,c2,c3,c4;int head[4005],Next[80005],to[80005],len[80005];int f[4005],p[4005],g[100005];int a[35][35],dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};int work(int x,int y,int z){    return ((x-1)*m+y-1)*4+z;}void add(int x,int y,int ok,int z){    tot++;    Next[tot]=head[x];    to[tot]=y;    if(ok==1) len[tot]=0;else len[tot]=z;    head[x]=tot;}void spfa(){    for(int i=2;i<=all;i++) f[i]=1e9;    t=0;w=1;    g[1]=1;    f[1]=0;    while(t<w)     {        t++;        x=g[t];        p[x]=0;        for(int i=head[x];i!=-1;i=Next[i])         if(f[x]+len[i]<f[to[i]])         {            f[to[i]]=f[x]+len[i];            if(p[to[i]]==0)             {                w++;                g[w]=to[i];                p[to[i]]=1;            }        }    }}int main(){    cin>>m>>n;    all=n*m*4;    for(int i=1;i<=all;i++) head[i]=-1;    for(int i=1;i<=n;i++)     for(int j=1;j<=m;j++)    {        scanf("%d",&a[i][j]);        a[i][j]++;    }    cin>>c1>>c2>>c3>>c4;    for(int i=1;i<=n;i++)     for(int j=1;j<=m;j++)     {        d1=work(i,j,1); //east        d2=work(i,j,2); //south        d3=work(i,j,3); //west        d4=work(i,j,4); //north        if(j+1<=m) add(d1,work(i,j+1,1),a[i][j]==1,c1); //Straight        if(i+1<=n) add(d2,work(i+1,j,2),a[i][j]==1,c1);        if(j-1>=1) add(d3,work(i,j-1,3),a[i][j]==1,c1);        if(i-1>=1) add(d4,work(i-1,j,4),a[i][j]==1,c1);        if(i+1<=n) add(d1,work(i+1,j,2),a[i][j]==2,c2);  //Right        if(j-1>=1) add(d2,work(i,j-1,3),a[i][j]==2,c2);        if(i-1>=1) add(d3,work(i-1,j,4),a[i][j]==2,c2);        if(j+1<=m) add(d4,work(i,j+1,1),a[i][j]==2,c2);        if(j-1>=1) add(d1,work(i,j-1,3),a[i][j]==3,c3); //Back        if(i-1>=1) add(d2,work(i-1,j,4),a[i][j]==3,c3);        if(j+1<=m) add(d3,work(i,j+1,1),a[i][j]==3,c3);        if(i+1<=n) add(d4,work(i+1,j,2),a[i][j]==3,c3);        if(i-1>=1) add(d1,work(i-1,j,4),a[i][j]==4,c4); //Left        if(j+1<=m) add(d2,work(i,j+1,1),a[i][j]==4,c4);        if(i+1<=n) add(d3,work(i+1,j,2),a[i][j]==4,c4);        if(j-1>=1) add(d4,work(i,j-1,3),a[i][j]==4,c4);    }           spfa();    ans=f[work(n,m,1)];    ans=min(ans,f[work(n,m,2)]);    ans=min(ans,f[work(n,m,3)]);    ans=min(ans,f[work(n,m,4)]);    cout<<ans;    return 0;}
0 0
原创粉丝点击