【Luogu】P3930 SAC E#1 - 一道大水题 Knight
【题目】洛谷10月月赛R1 提高组
【题意】给定n*n棋盘和<=16个棋子,给几个棋子种类和攻击范围,现我方只有一马,求能否吃王。
【算法】状压+BFS
【题解】16种棋子中,马不能吃马,直接处理马和王,那么就剩13个棋子,可以压成2^13表示棋盘现有棋子存活状态。
然后对vis[2^13][n][n]进行bfs。
细节:
1.攻击直到碰到其它棋子,那个碰到的棋子也算攻击范围内。
2.判断碰到棋子时,注意该棋子是否在当前局面存活。
3.多组数据,Q中途退出要清空。
学到了:
1.一份长代码要细心经营,视若珍宝,动键盘之前要冷静把思路和框架理清楚,过程中步步为营,慢慢写总能写完的。
2.不要轻易相信自己的代码没有bug了,尽量对拍,把小数据的中间结果输出和手算比较正确性,从而改掉尽可能多的错误。
3.不要害怕写长的复杂的代码,先做框架,然后一步一步把子过程做好,一份超长代码就慢慢构造出来了。
4.枚举对角线的姿势!
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f,maxn=;
int n,mp[<<][maxn][maxn],map[maxn][maxn],p[maxn][maxn],ans;
int cnt,tot,Tx,Ty,Sx,Sy;
bool vis[<<][maxn][maxn];
struct Node{int x,y;}c[],ch[];
struct cyc{int S,x,y,st;};
queue<cyc>Q;
void qishi(int S,int x,int y){
mp[S][x-][y+]=mp[S][x+][y+]=mp[S][x+][y-]=mp[S][x+][y+]=;
if(x->)mp[S][x-][y-]=mp[S][x-][y+]=;
if(y->)mp[S][x-][y-]=mp[S][x+][y-]=;
}
void king(int S,int x,int y){
mp[S][x-][y-]=mp[S][x-][y]=mp[S][x-][y+]=;
mp[S][x][y-]=mp[S][x][y+]=;
mp[S][x+][y-]=mp[S][x+][y]=mp[S][x+][y+]=;
}
bool m(int S,int x,int y){
if(map[x][y]<=)return ;
if(map[x][y]==||map[x][y]==)return ;
if(S&(<<(p[x][y]-)))return ;
return ;
}
void chengbao(int S,int x,int y){
for(int i=x-;i>=;i--)if(m(S,i,y))mp[S][i][y]=;else{mp[S][i][y]=;break;}
for(int i=x+;i<=n;i++)if(m(S,i,y))mp[S][i][y]=;else{mp[S][i][y]=;break;}
for(int i=y-;i>=;i--)if(m(S,x,i))mp[S][x][i]=;else{mp[S][x][i]=;break;}
for(int i=y+;i<=n;i++)if(m(S,x,i))mp[S][x][i]=;else{mp[S][x][i]=;break;}
}
void zhujiao(int S,int x,int y){
for(int i=;i<min(x,y);i++)if(m(S,x-i,y-i))mp[S][x-i][y-i]=;else{mp[S][x-i][y-i]=;break;}
for(int i=;i<=min(n-x,n-y);i++)if(m(S,x+i,y+i))mp[S][x+i][y+i]=;else{mp[S][x+i][y+i]=;break;}
for(int i=;i<=min(x,n-y);i++)if(m(S,x-i,y+i))mp[S][x-i][y+i]=;else{mp[S][x-i][y+i]=;break;}
for(int i=;i<=min(n-x,y);i++)if(m(S,x+i,y-i))mp[S][x+i][y-i]=;else{mp[S][x+i][y-i]=;break;}
}
void soldier(int S,int x,int y){
mp[S][x+][y-]=mp[S][x+][y+]=;
}
void check(int S,int x,int y,int st){
if(x<||x>n||y<||y>n||mp[S][x][y]||vis[S][x][y])return;
vis[S][x][y]=;
if(map[x][y]==)ans=st;
if(map[x][y]>=&&map[x][y]<=)if(S&(<<(p[x][y]-)))S^=(<<(p[x][y]-));
vis[S][x][y]=;
Q.push((cyc){S,x,y,st});
}
char s[maxn];
int main(){
while(scanf("%d",&n)==){
cnt=tot=;
memset(map,,sizeof(map));memset(p,,sizeof(p));memset(mp,,sizeof(mp));memset(vis,,sizeof(vis));
for(int i=;i<=n;i++){
scanf("%s",s+);
for(int j=;j<=n;j++){
if(s[j]=='K')map[i][j]=,c[++cnt].x=i,c[cnt].y=j;
if(s[j]=='X')map[i][j]=,Tx=i,Ty=j,c[++cnt].x=i,c[cnt].y=j;
if(s[j]=='O')Sx=i,Sy=j;
if(s[j]=='C')map[i][j]=,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
if(s[j]=='B')map[i][j]=,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
if(s[j]=='Q')map[i][j]=,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
if(s[j]=='P')map[i][j]=,ch[tot].x=i,ch[tot].y=j,p[i][j]=tot++;
}
}
for(int S=;S<(<<tot);S++){
for(int i=;i<=cnt;i++)if(map[c[i].x][c[i].y]==)qishi(S,c[i].x,c[i].y);else king(S,c[i].x,c[i].y);
for(int i=;i<tot;i++)if((<<i)&S){
int x=ch[i].x,y=ch[i].y;
if(map[x][y]==)chengbao(S,x,y);
if(map[x][y]==)zhujiao(S,x,y);
if(map[x][y]==)chengbao(S,x,y),zhujiao(S,x,y);
if(map[x][y]==)soldier(S,x,y);
}
mp[S][Tx][Ty]=;
}
if(mp[(<<tot)-][Sx][Sy]==){printf("-1\n");continue;}
while(!Q.empty())Q.pop();
Q.push((cyc){(<<tot)-,Sx,Sy,});vis[(<<tot)-][Sx][Sy]=;
ans=;
while(!Q.empty()){
cyc q=Q.front();Q.pop();
check(q.S,q.x-,q.y-,q.st+);check(q.S,q.x-,q.y+,q.st+);
check(q.S,q.x-,q.y-,q.st+);check(q.S,q.x-,q.y+,q.st+);
check(q.S,q.x+,q.y-,q.st+);check(q.S,q.x+,q.y+,q.st+);
check(q.S,q.x+,q.y-,q.st+);check(q.S,q.x+,q.y+,q.st+);
if(ans)break;
}
if(ans==)printf("-1\n");else printf("%d\n",ans);
}
return ;
}
【Luogu】P3930 SAC E#1 - 一道大水题 Knight的更多相关文章
- P3930 SAC E#1 - 一道大水题 Knight
TLE,额 ,有空再写吧. #include<queue> #include<cstdio> #include<vector> #include<algori ...
- [洛谷3930]SAC E#1 - 一道大水题 Knight
Description 他们经常在一起玩一个游戏,不,不是星际争霸,是国际象棋.毒奶色觉得F91是一只鸡.他在一个n×n的棋盘上用黑色的城堡(车).骑士(马).主教(象).皇后(副).国王(帅).士兵 ...
- 第三届山西省赛1004 一道大水题(scanf)
一道大水题 时间限制: C/C++ 2000ms; Java 4000ms 内存限制: 65535KB 通过次数: 44 总提交次数: 1020 问题描述 Dr. Pan作为上兰帝国ACM的总负责人, ...
- 【数据结构】 最小生成树(四)——利用kruskal算法搞定例题×3+变形+一道大水题
在这一专辑(最小生成树)中的上一期讲到了prim算法,但是prim算法比较难懂,为了避免看不懂,就先用kruskal算法写题吧,下面将会将三道例题,加一道变形,以及一道大水题,水到不用高级数据结构,建 ...
- 【Luogu】P3927 SAC E#1 - 一道中档题 Factorial
[题目]洛谷10月月赛R1 提高组 [题意]求n!在k进制下末尾0的个数,n<=1e18,k<=1e16. [题解]考虑10进制末尾0要考虑2和5,推广到k进制则将k分解质因数. 每个质因 ...
- 【Luogu】 P3928 SAC E#1 - 一道简单题 Sequence2
[题目]洛谷10月月赛R1 提高组 [算法]递推DP+树状数组 [题解]列出DP递推方程,然后用树状数组维护前后缀和. #include<cstdio> #include<cstri ...
- 【洛谷十月月测】 P3927 SAC E#1 - 一道中档题 Factorial
题目传送门:https://www.luogu.org/problemnew/show/P3927 题目大意:给你两个正整数n,k,求n!在k进制下末尾零的数量. 我们通过简单的数学分析,便可以发现, ...
- 2013年山东省第四届ACM大学生程序设计竞赛-最后一道大水题:Contest Print Server
点击打开链接 2226: Contest Print Server Time Limit: 1 Sec Memory Limit: 128 MB Submit: 53 Solved: 18 [Su ...
- SAC E#1 - 一道神题 Sequence1
题目背景 小强和阿米巴是好朋友. 题目描述 小强很喜欢数列.有一天,他心血来潮,写下了一个数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种:波动数列. 一个长度为n的波动数列满足对于任何i(1 < ...
随机推荐
- iOS AVAudioPlayer播放音频时声音太小
iOS AVAudioPlayer播放音频时声音太小 //引入AVFoundation类库,设置播放模式就可以了 do { try AVAudioSession.sharedInstance().ov ...
- 【Docker 命令】- attach命令
docker attach :连接到正在运行中的容器. 语法 docker attach [OPTIONS] CONTAINER 要attach上去的容器必须正在运行,可以同时连接上同一个contai ...
- 【Docker 命令】- kill命令
docker kill :杀掉一个运行中的容器. 语法 docker kill [OPTIONS] CONTAINER [CONTAINER...] OPTIONS说明: -s :向容器发送一个信号 ...
- java-自定义标签&&JSTL标签库详解
自定义标签是Jav aWeb的一部分非常重要的核心功能,我们之前就说过,JSP规范说的很清楚,就是Jsp页面中禁止编写一行Java代码,就是最好不要有Java脚本片段,下面就来看一下自定义标签的简介: ...
- [C/C++] C++模板定义格式
函数模板的格式: template <class 形参名,class 形参名,......> 返回类型 函数名(参数列表) { //函数体 } 类模板的格式为: template<c ...
- 【bzoj4196】[Noi2015]软件包管理器 树链剖分+线段树
题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...
- P1667 数列
题目描述 给定一个长度是n的数列A,我们称一个数列是完美的,当且仅当对于其任意连续子序列的和都是正的.现在你有一个操作可以改变数列,选择一个区间[X,Y]满足Ax +Ax+1 +…+ AY<0, ...
- [洛谷P2511][HAOI2008]木棍分割
题目大意:有$n(n\leqslant5\times10^4)$根木棍,连续放在一起,把它们分成$m(\leqslant10^3)$段,要求使得最长的段最短,问最短的长度以及方案数 题解:要使得最长的 ...
- [BZOJ2961] 共点圆 [cdq分治+凸包]
题面 BZOJ传送门 思路 首先考虑一个点$(x_0,y_0)$什么时候在一个圆$(x_1,y_1,\sqrt{x_1^2+y_1^2})$内 显然有:$x_1^2+y_1^2\geq (x_0-x_ ...
- [CEOI2004]锯木厂选址 斜率优化DP
斜率优化DP 先考虑朴素DP方程, f[i][k]代表第k个厂建在i棵树那里的最小代价,最后答案为f[n+1][3]; f[i][k]=min(f[j][k-1] + 把j+1~i的树都运到i的代价) ...