SGU 536 Berland Chess(状压+BFS)

题意:

给你一个期盼,你可以移动白皇来吃掉其他的黑棋,每种黑棋有攻击范围,
白皇不能走进去,问最少需要几步全部吃完。
很恶心的一个搜索,因为黑棋弧不动的,所有我们可以预处理处所有与的
被吃掉某些棋之后棋盘的情况。这个预处理实在太恶心了,处理完之后,
就是单纯的搜索了。

代码:

//
//  Created by  CQU_CST_WuErli
//  Copyright (c) 2015 CQU_CST_WuErli. All rights reserved.
//
// #include<bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
#include <sstream>
#define CLR(x) memset(x,0,sizeof(x))
#define OFF(x) memset(x,-1,sizeof(x))
#define MEM(x,a) memset((x),(a),sizeof(x))
#define For_UVa if (kase!=1) cout << endl
#define BUG cout << "I am here" << endl
#define lookln(x) cout << #x << "=" << x << endl
#define SI(a) scanf("%d",&a)
#define SII(a,b) scanf("%d%d",&a,&b)
#define SIII(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define rep(flag,start,end) for(int flag=start;flag<=end;flag++)
#define Rep(flag,start,end) for(int flag=start;flag>=end;flag--)
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
#define Root 1,n,1
#define BigInteger bign
template <typename T> T gcd(const T& a,const T& b) {return b==0?a:gcd(b,a%b);}
const int MAX_L=2005;// For BigInteger
const int INF_INT=0x3f3f3f3f;
const long long INF_LL=0x7fffffff;
const int MOD=1e9+7;
const double eps=1e-9;
const double pi=acos(-1);
typedef long long  ll;
using namespace std;

int n,m;
int mp[16][16];
int dp[1<<15][16][16];
int ban[1<<15][16][16];
int kind[20];

struct State{
    int state;
    int x,y;
    State(int state,int x,int y):state(state),x(x),y(y){}
};

int main(){
#ifdef LOCAL
    freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);
//  freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);
#endif
    while (SII(n,m)==2) {
        int sx,sy;
        int cnt=0;
        vector<pair<int,int> > v;
        rep(i,1,n) rep(j,1,m) {
            char c;
            cin >> c;
            if (c=='.') mp[i][j]=-1;
            else if (c=='*') {
                mp[i][j]=-1;
                sx=i;sy=j;
            }
            else if (c=='K') {
                mp[i][j]=cnt;
                kind[cnt++]=1;
                v.push_back(make_pair(i,j));
            }
            else if (c=='B') {
                mp[i][j]=cnt;
                kind[cnt++]=2;
                v.push_back(make_pair(i,j));
            }
            else if (c=='R') {
                mp[i][j]=cnt;
                kind[cnt++]=3;
                v.push_back(make_pair(i,j));
            }
        }
        CLR(ban);MEM(dp,0x3f);
        int tmp[16][16];
        for (int sta=0;sta<1<<cnt;sta++) {
            memcpy(tmp,mp,sizeof(mp));
            for (int i=0;i<v.size();i++) {
                int ti=v[i].first,tj=v[i].second;
                if (!((sta>>mp[ti][tj])&1)) tmp[ti][tj]=-1;
            }
            for (int i=1;i<=n;i++) {
                for (int j=1;j<=m;j++) {
                    if (tmp[i][j]==-1) continue;
                    if (kind[tmp[i][j]]==1) {       //'K'
                        for (int dx=-2;dx<=2;dx++) {
                            for (int dy=-2;dy<=2;dy++) {
                                if (abs(dx)+abs(dy)==3) {
                                    int tx=i+dx,ty=j+dy;
                                    if (tx<1 || ty<1 || tx>n || ty>m) continue;
                                    ban[sta][tx][ty]=1;
                                }
                            }
                        }
                    }
                    else if (kind[tmp[i][j]]==2) {
                        for (int dx=-1;dx<=1;dx+=2) {
                            for (int dy=-1;dy<=1;dy+=2) {
                                int tx=i+dx,ty=j+dy;
                                while (tx>=1 && tx<=n && ty>=1 && ty<=m) {
                                    ban[sta][tx][ty]=1;
                                    if (tmp[tx][ty]!=-1) break;
                                    tx+=dx;ty+=dy;
                                }
                            }
                        }
                    }
                    else if (kind[tmp[i][j]]==3) {
                        int dx[4]={1,-1,0,0};
                        int dy[4]={0,0,1,-1};
                        for (int k=0;k<4;k++) {
                            int tx=i+dx[k],ty=j+dy[k];
                            while (tx>=1 && tx<=n && ty>=1 && ty<=m) {
                                ban[sta][tx][ty]=1;
                                if (tmp[tx][ty]>=0) break;
                                tx+=dx[k];ty+=dy[k];
                            }
                        }
                    }
                }
            }
        }
        // search
        queue<State> q;
        q.push(State((1<<cnt)-1,sx,sy));
        dp[(1<<cnt)-1][sx][sy]=0;
        while (q.size()) {
            State now=q.front();
            q.pop();
            int x=now.x,y=now.y;
//          cout << x << ' ' << y << endl;
            int state=now.state;
//          lookln(state);
            for (int dx=-1;dx<=1;dx++){
                for (int dy=-1;dy<=1;dy++){
                    if (dx==0 && dy==0) continue;
                    int tx=x+dx,ty=y+dy;
                    if (tx<1 || ty<1 || tx>n || ty>m) continue;
                    if (ban[state][tx][ty]) continue;
                    if (mp[tx][ty]!=-1 && ((state>>mp[tx][ty])&1)) {
                        int tt=state&~(1<<mp[tx][ty]);
                        if (dp[state][x][y]+1<dp[tt][tx][ty]) {
                            dp[tt][tx][ty]=dp[state][x][y]+1;
                            q.push(State(tt,tx,ty));
                        }
                    }
                    else {
                        if (dp[state][x][y]+1<dp[state][tx][ty]) {
                            dp[state][tx][ty]=dp[state][x][y]+1;
                            q.push(State(state,tx,ty));
                        }
                    }
                }
            }
        }
        int ans=INF_INT;
        for (int i=0;i<v.size();i++) ans=min(ans,dp[0][v[i].first][v[i].second]);
        if (ans>=INF_INT) ans=-1;
        if (cnt==0) ans=0;
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值