Description

他们经常在一起玩一个游戏,不,不是星际争霸,是国际象棋。毒奶色觉得F91是一只鸡。他在一个n×n的棋盘上用黑色的城堡(车)、骑士(马)、主教(象)、皇后(副)、国王(帅)、士兵(卒)摆了一个阵。然而F91觉得毒奶色是一只鸡。他发起了挑战:他要操纵一个白色骑士,不经过任何一个棋子的攻击范围(F91可以连续行动,而毒奶色的棋子不会动,除非白骑士进入了对方的攻击范围),并击杀毒奶色的国王(即进入黑国王所在的位置)。请告诉F91他最少需要多少步骤来完成这一项壮举。

注意:

  • 当F91的白骑士走到毒奶色的棋子所在的格子上的时候,会击杀(吃掉)该棋子。这个棋子也就不再对F91的白骑士有威胁了。
  • 如果白骑士开场就在黑子的攻击范围内,则立刻被击杀、F91立刻失败。
  • 即使白骑士在攻击王的瞬间进入了其他棋子攻击范围(即其他棋子"看护"着王所在的格子),依然算F91获胜。

攻击范围:

城堡:横、竖方向所有位置,直到被一个其他棋子阻拦。

..#..
..#..
##C##
..#..
..#..

骑士:横2竖1或者横1竖2的所有位置(最多8个,类似日字)。

.#.#.
#...#
..K..
#...#
.#.#.

主教:斜向(45°)所有位置,直到被一个其他棋子阻拦。

#...#
.#.#.
..B..
.#.#.
#...#

皇后:城堡和主教的结合体(既能横/竖向攻击,也能45°角斜向攻击,直到被其他棋子阻挡)。

#.#.#
.###.
##Q##
.###.
#.#.#

国王:身边8连通位置的8个格子。

.....
.###.
.#X#.
.###.
.....

士兵:左下方/右下方(45°)的格子(最多2个)。

.....
.....
..P..
.#.#.
.....

其中字母表示棋子类型,参考输入格式。

'#'表示可攻击范围。

Input

输入包含多组数据。

每一组数据中,第一行一个整数n表示棋盘规模。

接下来n行,每行一个长度为n的字符串。描述棋盘的格局。

其中:

.表示空

O表示白骑士

C表示黑城堡

K表示黑骑士

B表示黑主教

Q表示黒皇后

X表示黑国王

P表示黑士兵

Output

对于每一个测试数据,每行输出一个整数,表示F91的最小步数。

如果无论F91如何行动也无法击杀黑国王,输出-1。

Sample Input

8

......X.

........

.O......

...P.Q.C8

.....B..

........

...K....

........

Sample Output

7

HINT

输入最多包含5组数据。

对于20%的数据,毒奶色只有国王。n <= 8。

对于30%的数据,毒奶色只有国王、骑士。n <= 8。

对于60%的数据,毒奶色只有国王、骑士、王后。n <= 50。

对于100%的数据,毒奶色可以有全套16颗棋子(2城堡,2骑士,2主教,1后,1王,8兵)。n <= 50。

温馨提示:时间限制可能比想象之中还要更紧一点,请注意实现细节以保证性能。

样例2解释:

一种可行的做法是:

......X.
.3..6...
.O5.....
4.2P.Q.C
1....B..
........
...K....
........

这题看起来真是恶心,不过知道写法之后也还好。。。

我们设f[x][y][sta]代表当前在(x,y)这个点,吃掉的黑棋状态为sta。bfs每次转移,判断(x,y,sta)这个三元组是否可行(暴力判断可行),然后循环队列优化,碰到'X'就输出答案。

这题我TM还RE了好几次,最后发现数据里n=55???说好的n<=50呢???

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include <unordered_set>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x>=10) print(x/10);
putchar(x%10+'0');
}
const int N=60,M=1e5;
const int dx[8]={-2,-2,-1,-1,1,1,2,2};
const int dy[8]={-1,1,-2,2,-2,2,-1,1};
struct S1{int x,y,dis,sta;}h[M+10];
unordered_set<int>vis[N][N];
char A[N][N];
int ID[N][N],n;
int in_map(int x,int y){return x>0&&x<=n&&y>0&&y<=n;}
bool check(int sta,int x,int y){
if (vis[x][y].count(sta)) return false;
for (int i=x+1;i<=n;i++){
if (A[i][y]!='.'&&!(sta&(1<<ID[i][y]))){
if (A[i][y]=='C'||A[i][y]=='Q')
return false;
break;
}
}
for (int i=x-1;i>=0;i--){
if (A[i][y]!='.'&&!(sta&(1<<ID[i][y]))){
if (A[i][y]=='C'||A[i][y]=='Q')
return false;
break;
}
}
for (int j=y+1;j<=n;j++){
if (A[x][j]!='.'&&!(sta&(1<<ID[x][j]))){
if (A[x][j]=='C'||A[x][j]=='Q')
return false;
break;
}
}
for (int j=y-1;j>=0;j--){
if (A[x][j]!='.'&&!(sta&(1<<ID[x][j]))){
if (A[x][j]=='C'||A[x][j]=='Q')
return false;
break;
}
}
for (int i=x+1,j=y+1;i<=n&&j<=n;i++,j++){
if (A[i][j]!='.'&&!(sta&(1<<ID[i][j]))){
if (A[i][j]=='B'||A[i][j]=='Q')
return false;
break;
}
}
for (int i=x+1,j=y-1;i<=n&&j>=0;i++,j--){
if (A[i][j]!='.'&&!(sta&(1<<ID[i][j]))){
if (A[i][j]=='B'||A[i][j]=='Q')
return false;
break;
}
}
for (int i=x-1,j=y+1;i>=0&&j<=n;i--,j++){
if (A[i][j]!='.'&&!(sta&(1<<ID[i][j]))){
if (A[i][j]=='B'||A[i][j]=='Q')
return false;
break;
}
}
for (int i=x-1,j=y-1;i>=0&&j>=0;i--,j--){
if (A[i][j]!='.'&&!(sta&(1<<ID[i][j]))){
if (A[i][j]=='B'||A[i][j]=='Q')
return false;
break;
}
}
for (int k=0;k<8;k++){
int tx=x+dx[k],ty=y+dy[k];
if (!in_map(tx,ty)) continue;
if (A[tx][ty]=='K') return false;
}
if (x!=1&&((y!=1&&!(sta&(1<<ID[x-1][y-1]))&&A[x-1][y-1]=='P')||(y!=n&&!(sta&(1<<ID[x-1][y+1]))&&A[x-1][y+1]=='P')))
return false;
for (int i=x-1;i<=x+1;i++){
for (int j=y-1;j<=y+1;j++){
if (!in_map(i,j)) continue;
if (A[i][j]=='X') return false;
}
}
return true;
}
int bfs(int ox,int oy){
int head=0,tail=1;
h[1]=(S1){ox,oy,0,0};
vis[ox][oy].insert(0);
while (head!=tail){
if (++head>M) head=1;
int Nx=h[head].x,Ny=h[head].y;
for (int k=0;k<8;k++){
int tx=Nx+dx[k],ty=Ny+dy[k],sta=h[head].sta;
if (!in_map(tx,ty)) continue;
if (A[tx][ty]=='X') return h[head].dis+1;
if (A[tx][ty]!='.') sta|=1<<ID[tx][ty];
if (check(sta,tx,ty)){
if (++tail>M) tail=1;
h[tail]=(S1){tx,ty,h[head].dis+1,sta};
vis[tx][ty].insert(sta);
}
}
}
return -1;
}
void init(){memset(ID,255,sizeof(ID));}
int main(){
while (~scanf("%d",&n)){
init(); int tot=0,ox=0,oy=0;
for (int i=1;i<=n;i++){
scanf("%s",A[i]+1);
for (int j=1;j<=n;j++){
if (A[i][j]=='O') ox=i,oy=j,A[i][j]='.';
else if (A[i][j]!='.') ID[i][j]=++tot;
vis[i][j].clear();
}
}
if (!check(0,ox,oy)){
printf("-1\n");
continue;
}
printf("%d\n",bfs(ox,oy));
}
return 0;
}

[洛谷3930]SAC E#1 - 一道大水题 Knight的更多相关文章

  1. 【Luogu】P3930 SAC E#1 - 一道大水题 Knight

    [题目]洛谷10月月赛R1 提高组 [题意]给定n*n棋盘和<=16个棋子,给几个棋子种类和攻击范围,现我方只有一马,求能否吃王. [算法]状压+BFS [题解]16种棋子中,马不能吃马,直接处 ...

  2. 洛谷 P3927 SAC E#1 - 一道中档题 Factorial【数论//】

    题目描述 SOL君很喜欢阶乘.而SOL菌很喜欢研究进制. 这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘. SOL菌表示不服,立刻就要算这个数在k进制表示下末尾0的个数. 但是SOL菌太菜了于是请 ...

  3. 洛谷P3929 SAC E#1 - 一道神题 Sequence1【枚举】

    题目描述 小强很喜欢数列.有一天,他心血来潮,写下了一个数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种:波动数列. 一个长度为n的波动数列满足对于任何i(1 <= i < n),均有: ...

  4. 洛谷P3928 SAC E#1 - 一道简单题 Sequence2

    提交地址 题目背景 小强和阿米巴是好朋友. 题目描述 小强喜欢数列.有一天,他心血来潮,写下了三个长度均为n的数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种,波动数列. 阿米巴把他的喜好告诉了小强. ...

  5. 洛谷-P3927 SAC E#1 - 一道中档题 Factorial

    原址 题目背景 数据已修改 SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友. 题目描述 SOL君很喜欢阶乘.而SOL菌很喜欢研究进制. 这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘. ...

  6. [洛谷P3927]SAC E#1 - 一道中档题 Factorial

    题目大意:求$n!$在$k(k>1)$进制下末尾0的个数. 解题思路:一个数在十进制转k进制时,我们用短除法来做.容易发现,如果连续整除p个k,则末尾有p个0. 于是问题转化为$n!$能连续整除 ...

  7. [洛谷P3929]SAC E#1 - 一道神题 Sequence1

    题目大意:给你一串数列,问你能否改变1个数或不改,使它变成波动数列? 一个长度为n的波动数列满足对于任何i(1 <= i < n),均有: a[2i-1] <= a[2i] 且 a[ ...

  8. P3930 SAC E#1 - 一道大水题 Knight

    TLE,额 ,有空再写吧. #include<queue> #include<cstdio> #include<vector> #include<algori ...

  9. 洛谷P3926 SAC E#1 - 一道不可做题 Jelly【模拟/细节】

    P3926 SAC E#1 - 一道不可做题 Jelly [链接]:https://www.luogu.org/problem/show?pid=3926 题目背景 SOL君(炉石主播)和SOL菌(完 ...

随机推荐

  1. codevs2597 团伙

    题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友 ...

  2. set(集合)数据类型【七】

    一.概述:(类似于Java的Set,不允许有重复元素) 在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加.删除或判断某一元素是否存 ...

  3. Linux中kill,pkill,killall和xkill命令汇总讲解

    终止一个进程或终止一个正在运行的程式,一般是通过 kill .killall.pkill.xkill 等进行.比如一个程式已死掉,但又不能退出,这时就应该考虑应用这些工具. 另 外应用的场合就是在服务 ...

  4. 【进击后端】linux安装最新版nodejs

    nodejs下载:https://nodejs.org/zh-cn/download/ 1.cd /root/download 2.wget https://nodejs.org/dist/v6.11 ...

  5. [bzoj4826][Hnoi2017]影魔_单调栈_主席树

    影魔 bzoj-4826 Hnoi-2017 题目大意:给定一个$n$个数的序列$a$,求满足一下情况的点对个数: 注释:$1\le n,m\le 2\cdot 10^5$,$1\le p1,p2\l ...

  6. HDU——1498 50 years, 50 colors

    50 years, 50 colors Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  7. 使用Tornado实现http代理

    0x00 http代理 http代理的用处非常多,市面上也有公开的代理,可是有时候为了工作须要,比方分析应用层流量.做数据訪问控制.甚至做监控等等.Tornado提供了一些非常方便的环境和API,我们 ...

  8. 卸载MySQL 5.0

    昨天在Navicat for mysql中导入一个脚本,执行.出现乱码. 考虑到可能是版本号问题,就想卸载了又一次安装MYSQL,这一卸载倒是出了问题.导致安装的时候安装不上. 后来无意发现是卸载的时 ...

  9. ViewPager学习之仿微信主界面

    由于素材的原因,这里都是从网上找的图片,所以所谓的仿微信实际上最后成了下图这货.. .,点击变色也是自己用的windows自带绘图的颜料桶填充的空白. .. watermark/2/text/aHR0 ...

  10. PHP数组去空项

    $strDelCodes = "A;B;;C;;C;D;;;D;D";$rsArray = array_values (array_unique (array_diff (spli ...