书上具体所有题目:http://pan.baidu.com/s/1hssH0KO

代码:(Accepted,0 ms)

//UVa1589
#include<iostream>
#include<cmath>
#define P(x,y) Pi[x].position[y]
using namespace std;
int N;//2<=N<=7
bool A[4];//around,储存"将"周围是不是已经不能走了 0上 1左 2下 3右
struct piece {
char name;
int position[2];//0x 1y
}Pi[10]; inline bool f1(int i, int j, bool po) {//判断第j个子是否堵在第i个子前面,针对"车"和"帅"和"炮"
if (P(i, (po + 1) % 2) != P(j, (po + 1) % 2)) return 0;
int ii = P(i, po) - P(0, po), jj = P(j, po) - P(0, po);
if (ii > 0 && jj > 0 && ii > jj) return 1;
if (ii < 0 && jj < 0 && ii < jj) return 1;
return 0;
}
inline bool f2(int i) {//判断第i个子是不是在"将"周围
if (P(i, 0) == P(0, 0) && abs(P(i, 1) - P(0, 1)) == 1) return 1;
if (P(i, 1) == P(0, 1) && abs(P(i, 0) - P(0, 0)) == 1) return 1;
return 0;
}
bool f3(int i, int xx, int yy) {//判断"马"是否可以到达"将"周围
if ((abs(xx) == 2 && abs(yy) == 1) || (abs(xx) == 1 && abs(yy) == 2)) {
for (int j = 0;j <= N;++j) {
if (P(j, 0) == P(i, 0) - int(xx / 2) && P(j, 1) == P(i, 1) - int(yy / 2)) return 0;
//cerr <<"H:"<<i<<' '<<j<<'\t'<< P(j, 0) << ' ' << P(i, 0) - int(xx / 2) << '\t' << P(j, 0) << ' ' << P(i, 1) - int(yy / 1) << '\n';//-------------------
}
return 1;
}
return 0;
}
void GR(int i, bool po) {//"将"和"车"的函数
if (P(i, (po + 1) % 2)>P(0, (po + 1) % 2) + 1 || P(i, (po + 1) % 2) < P(0, (po + 1) % 2) - 1) return;
int j = 1;
for (;j <= N&&!f1(i, j, po);++j);
if (j > N) {
if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) - 1) { if (!f2(i)) A[(po + 1) % 2] = 1; }
else if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) + 1) { if (!f2(i))A[(po + 1) % 2 + 2] = 1; }
else if (f2(i)) P(i, po) - P(0, po) > 0 ? A[po] = 1 : A[po + 2] = 1;
else A[po] = A[po + 2] = 1;
}
}
void H(int i) {//"马"的函数
if (f2(i)) return;
if (!A[0] && f3(i, P(i, 0) - (P(0, 0) - 1), P(i, 1) - P(0, 1))) A[0] = 1;
if (!A[1] && f3(i, P(i, 0) - P(0, 0), P(i, 1) - (P(0, 1) - 1))) A[1] = 1;
if (!A[2] && f3(i, P(i, 0) - (P(0, 0) + 1), P(i, 1) - P(0, 1))) A[2] = 1;
if (!A[3] && f3(i, P(i, 0) - P(0, 0), P(i, 1) - (P(0, 1) + 1))) A[3] = 1;
}
void C(int i, bool po) {//"炮"的函数
if (f2(i) || P(i, (po + 1) % 2) > P(0, (po + 1) % 2) + 1 || P(i, (po + 1) % 2) < P(0, (po + 1) % 2) - 1) return;
int flag = 0;
for (int j = 1;j <= N;++j) if (f1(i, j, po)) ++flag;
if (flag == 1) {
if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) - 1) A[(po + 1) % 2] = 1;
else if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) + 1) A[(po + 1) % 2 + 2] = 1;
else {
int j = 1;
for (;j <= N;++j) if (f1(i, j, po) && f2(j)) break;
if (j <= N) P(i, po) - P(0, po) > 0 ? A[po] = 1 : A[po + 2] = 1;
else A[po] = A[po + 2] = 1;
}
}
} int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while ((cin >> N >> P(0, 0) >> P(0, 1)) && N && P(0, 0) && P(0, 1)) {
for (int i = 1;i <= N;++i)
cin >> Pi[i].name >> P(i, 0) >> P(i, 1);
A[0] = (P(0, 0) == 1 ? 1 : 0);
A[1] = (P(0, 1) == 4 ? 1 : 0);
A[2] = (P(0, 0) == 3 ? 1 : 0);
A[3] = (P(0, 1) == 6 ? 1 : 0);
//cerr << "A:" << A[0] << '\t' << A[1] << '\t' << A[2] << '\t' << A[3] << "\n";//--------
for (int i = 1;i <= N;++i) {
if (Pi[i].name == 'G') GR(i, 0);
else if (Pi[i].name == 'R') GR(i, 0), GR(i, 1);
else if (Pi[i].name == 'H') H(i);
else C(i, 0), C(i, 1);
}
int i;
//cerr << "A:" << A[0] << '\t' << A[1] << '\t' << A[2] << '\t' << A[3] << "\n";//--------
for (i = 0;i < 4 && A[i];++i);
cout << (i < 4 ? "NO" : "YES") << '\n';
}
return 0;
}

分析:

看着挺烦的,以为会调试很久,有那么多情况,感觉还不好找出错的点。结果两遍就AC了,喜出望外~

我的思路是,判断每个子有没有把“将”周围堵住,对棋子大循环。同时我没有定义9*10的大棋盘。(现在想想定义了个棋盘好像简单好多。甚至可以打表查看哪里红子可以到达。或许我太过在意空间的占用了)

A[4]的0上 1左 2下 3右是有顺序要求的,这样定义可以方便地和po对应起来。

车炮帅的攻击范围都是直线,所以定义的函数只针对其中一个方向,而G只能是向x轴方向出击,所以是只使用向x轴(po=0)方向的函数,而车和炮要使用两次函数。这三者有两种情况将军,第一是指向“将”旁边,使“将”无法向旁边行走。另一种是直接指向“将”,使之只能往旁边走不能在车炮指向的方向行走。三者都得考虑被堵住看不见“将”的情况。

不过这题有个小bug,就是将和帅面对面的情况,将可以直接飞过去翻盘赢了,无需躲闪。但是题目好像没有考虑这种情况,应该是规避了这类输入数据。我也是点击“Submit”时突然想起来这个情况没写。。。不过竟然AC了,那就算了。。。

还有就是车和炮直接在将旁边的情况,将可以吃掉它们消除威胁(当然前提是没有别人可以吃这个位置)。这个情况下,比如红车在(1,6),黑将在(1,5),那么黑将可以向右吃掉它,但是不能向左,因为向左进入(1,4)后车依然可以吃“将”。这是比较特殊的。

还有就是这一段:

//在GR(...)函数的最后几行
if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) - 1) { if (!f2(i)) A[(po + 1) % 2] = 1; }
else if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) + 1) { if (!f2(i))A[(po + 1) % 2 + 2] = 1; }

本来我写的是

if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) - 1) A[(po + 1) % 2] = 1;
else if (P(i, (po + 1) % 2) == P(0, (po + 1) % 2) + 1) A[(po + 1) % 2 + 2] = 1;

没有后面的if。结果出现的问题就是当比如车在(1,6),将在(1,5)时,会判定为在针对x轴方向时,(1,6)(即将右侧,即A[3])是将不可以走的。

还有炮的函数C,对于该函数最后几行,

else {
int j = 1;
for (;j <= N;++j) if (f1(i, j, po) && f2(j)) break;
if (j <= N) P(i, po) - P(0, po) > 0 ? A[po] = 1 : A[po + 2] = 1;
else A[po] = A[po + 2] = 1;
}

意思是,如果炮架子刚好在将前面,那么炮只能攻击将的后面(即“将”不能后移),将前面即跑架子所在那个点打不到。

马的函数竟然算是最简单的了。。判断够不够得到将旁边的点,已及马有没有蹩脚即可。

附:uDebug上看到的测试数据:

2 1 4

G 10 5

R 6 4

3 1 5

H 4 5

G 10 5

C 7 5

2 1 5

R 4 4

G 10 5

3 1 5

G 10 4

R 5 5

H 3 7

4 1 5

G 10 4

C 6 5

H 5 5

R 1 1

5 1 5

G 10 4

C 6 5

H 5 5

H 4 5

R 1 1

3 1 5

G 10 4

C 2 7

H 3 7

3 1 5

G 10 4

R 5 5

R 1 6

4 1 5

G 10 4

R 5 5

R 1 6

H 3 7

0 0 0

[刷题]算法竞赛入门经典(第2版) 4-1/UVa1589 - Xiangqi的更多相关文章

  1. [刷题]算法竞赛入门经典(第2版) 4-6/UVa508 - Morse Mismatches

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 代码:(Accepted,10 ms) //UVa508 - Morse Mismatches #include< ...

  2. [刷题]算法竞赛入门经典(第2版) 5-15/UVa12333 - Revenge of Fibonacci

    题意:在前100000个Fibonacci(以下简称F)数字里,能否在这100000个F里找出以某些数字作为开头的F.要求找出下标最小的.没找到输出-1. 代码:(Accepted,0.250s) / ...

  3. [刷题]算法竞赛入门经典(第2版) 5-13/UVa822 - Queue and A

    题意:模拟客服MM,一共有N种话题,每个客服MM支持处理其中的i个(i < N),处理的话题还有优先级.为了简化流程方便出题,设每个话题都是每隔m分钟来咨询一次.现知道每个话题前来咨询的时间.间 ...

  4. [刷题]算法竞赛入门经典(第2版) 4-5/UVa1590 - IP Networks

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 代码:(Accepted,0 ms) //UVa1590 - IP Networks #include<iost ...

  5. [刷题]算法竞赛入门经典(第2版) 6-7/UVa804 - Petri Net Simulation

    题意:模拟Petri网的执行.虽然没听说过Petri网,但是题目描述的很清晰. 代码:(Accepted,0.210s) //UVa804 - Petri Net Simulation //Accep ...

  6. [刷题]算法竞赛入门经典(第2版) 6-6/UVa12166 - Equilibrium Mobile

    题意:二叉树代表使得平衡天平,修改最少值使之平衡. 代码:(Accepted,0.030s) //UVa12166 - Equilibrium Mobile //Accepted 0.030s //# ...

  7. [刷题]算法竞赛入门经典(第2版) 6-1/UVa673 6-2/UVa712 6-3/UVa536

    这三题比较简单,只放代码了. 题目:6-1 UVa673 - Parentheses Balance //UVa673 - Parentheses Balance //Accepted 0.000s ...

  8. [刷题]算法竞赛入门经典(第2版) 5-16/UVa212 - Use of Hospital Facilities

    题意:模拟患者做手术. 其条件为:医院有Nop个手术室.准备手术室要Mop分钟,另有Nre个恢复用的床.准备每张床要Mre分钟,早上Ts点整医院开张,从手术室手术完毕转移到回复床要Mtr分钟.现在医院 ...

  9. [刷题]算法竞赛入门经典(第2版) 5-11/UVa12504 - Updating a Dictionary

    题意:对比新老字典的区别:内容多了.少了还是修改了. 代码:(Accepted,0.000s) //UVa12504 - Updating a Dictionary //#define _XieNao ...

  10. [刷题]算法竞赛入门经典(第2版) 5-10/UVa1597 - Searching the Web

    题意:不难理解,照搬题意的解法. 代码:(Accepted,0.190s) //UVa1597 - Searching the Web //#define _XIENAOBAN_ #include&l ...

随机推荐

  1. Linux之kill,pkill,killall命令

    kill,pkill,killall这些命令都是用来杀死进程的 查找进程的方法: ps -ef|grep pidof 进程名 ps命令 http://www.cnblogs.com/along1226 ...

  2. webpack独立打包与缓存处理

    关于 微信公众号:前端呼啦圈(Love-FED) 我的博客:劳卜的博客 知乎专栏:前端呼啦圈 前言 先前写了一篇webpack入门的文章<webpack入门必知必会>,简单介绍了webpa ...

  3. 自己开发图表插件,脱离echart

    前言 由于公司业务需要做一些图标来展示一些数据,之前都是用百度的echart.js.这次放弃使用它转而自己开发是有几个原因1.echart文件太大,有些功能用不到2.echart样式不易扩展3.需求简 ...

  4. Unity SteamVR插件集成

    重要组件 SteamVR_Camera VR摄像机,主要功能是将Unity摄像机的画面进行变化,形成Vive中的成像画面 使用方法: l 在任一个摄像机上增加脚本 l 点击Expand按钮 完成以上操 ...

  5. 关于commonjs,AMD,CMD之间的异同

    1.简介 随着前端业务复杂度的增加,模块化成为一个大的趋势.而在ES6还未被浏览器所支持的情况下,commonjs作为ES6中标准模块加载方案,在客服端中的支持情况并不好,现在在客服端中有2中模块化的 ...

  6. 手机自动化测试:appium源码分析之bootstrap三

    手机自动化测试:appium源码分析之bootstrap三   研究bootstrap源码,我们可以通过代码的结构,可以看出来appium的扩展思路和实现方式,从中可以添加我们自己要的功能,针对app ...

  7. Lombok : 让你写 Java代码像C#一样爽

    前言 我曾经是一名 .Net 开发,如今的我是一名 Java 开发者.在我享受着 Java 成熟的生态时,我常常怀念 c# 简洁的语法:自动属性.类型推断.自动初始化器 .... 鱼,我所欲也,熊掌亦 ...

  8. windows server 定期备份数据库脚本

    将以下文件保存为.bat脚本,在计划任务中添加定时任务运行此脚本即可.脚本中的备份目录,数据库目录和压缩文件目录请自行修改. @echo off rem 当前路径切换到备份数据库目录 cd D:\wa ...

  9. Spring基础学习(五)—事务管理

    一.事务基本认识 1.事务的概述      为了保证数据库中数据的一致性,数据的操作应当是离散的成组的逻辑单元.当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应当全部视 ...

  10. windows系统System32中各种实用的工具

    工具类 这些工具可以直接打开运行  输入名字就可以调出来了 我还会上传一个java程序,运行后会显示一个界面,直接调用这些工具 1.SnippingTool.exe   截图 2.calc.exe   ...