Wumpus ZOJ月赛-3890

Wumpus

注意题目的黑体字,所有示例都只有一堆黄金。所以不存在开不开枪的状态;

//一道广搜题,扩展时有三个状态左转、右转、前进;
//收取宝藏可以在前进的时候判断;状态的标记可以用
//一个四维数组标记即:坐标,方向,宝藏是否全部拾取;

# include <queue>
# include <cstdio>
# include <cstring>
# include <iostream>
using namespace std;

int n,change[30][30],vis[30][30][4][2],sum,flag;
int d[4][2] = {0,-1,-1,0,0,1,1,0};

struct  Point{
    int m[30][30];
    int x,y,f,step,t,flag;
    Point operator = (const Point &a){
        x = a.x;y = a.y;f = a.f;step = a.step;t = a.t;flag = a.flag;
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++)    m[i][j] = a.m[i][j];
        }
    }
}s;

void bfs(){
    queue <Point> q;
    s.x = n-1;
    s.y = s.step = s.t = s.flag= 0;s.f = 2;
    vis[n-1][0][s.f][0] = 1;
    q.push(s);
    while(!q.empty())
    {
        Point temp = q.front();q.pop();
        for(int i = 0;i < 3;i++){
            Point e = temp;
            if(e.x == n-1 && e.y == 0 && e.flag == 1){
                e.step++;
                flag = 1;
                printf("%d\n",sum*1000 - e.step*10);
                return ;
            }
            if(i == 0){
                e.f = (e.f - 1 + 4) % 4,e.step++;
                if(!vis[e.x][e.y][e.f][e.flag]){
                    vis[e.x][e.y][e.f][e.flag]=1,q.push(e);
                }
            }
            else if(i == 1){
                e.f = (e.f + 1) % 4,e.step++;
                if(!vis[e.x][e.y][e.f][e.flag]){
                    vis[e.x][e.y][e.f][e.flag]=1,q.push(e);
                }
            }
            else if(i == 2){
                e.x += d[e.f][0],e.y += d[e.f][1],e.step++;
                if(e.x>=0 && e.x<n && e.y>=0 && e.y<n && !vis[e.x][e.y][e.f][e.flag]
                   && (e.m[e.x][e.y]==0 || e.m[e.x][e.y]==3)){
                    q.push(e);
                    vis[e.x][e.y][e.f][e.flag] = 1;
                    if(e.m[e.x][e.y] == 3){
                        e.m[e.x][e.y] = 0;
                        e.step++,e.t++;
                        if(e.t == sum)    e.flag = 1;
                        vis[e.x][e.y][e.f][e.flag] = 1;
                        q.push(e);
                    }
                }
            }
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int a,b,c,f = 0;
        sum = flag = 0;
        memset(change,0,sizeof(change));
        memset(vis,0,sizeof(vis));
        scanf("%d",&n);
        while(scanf("%d%d%d",&a,&b,&c)&& a != -1){
            change[b][c] = a;
            if(a == 2 && !b && !c)  f = 1;
            if(a == 3)  sum ++;
        }
        for(int i = 0;i < n;i++){
            for(int k = 0,j = n - 1;k < n && j >= 0;k++,j--)    s.m[j][i] = change[i][k];
        }
        if(f || !sum){
            printf("-1\n");     continue;
        }
        else    bfs();
        if(!flag)   printf("-1\n");
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值