SGU109 各类构造法 【副对角线法】【染色法】
来源:互联网 发布:天庭淘宝店 txt下载 编辑:程序博客网 时间:2024/05/01 09:09
【SGU109】
世界著名的魔术师大卫科波菲尔(David Copperfield喜欢)给人们看这个把戏:一个N*N的的有着不同颜色块的图片在电视屏幕上,让我们给整张图片按照下面的方式编号
1 2 ... N
N+1 N+2 ... 2N
N*(N-1)+1 N*(N-1)+2 ... N*N
所有观众首先将手指指向左上角的小格(1号图案)然后魔术开始:魔术师命令观众在图案中移动手指 K1次(一次移动是指移动到当前图案上下左右的另一个图案),之后魔术师轻挥手指,有一些图案所在的格子不见了(被删掉的格子以后不能经过),魔术师解释说"你不可能在这里!", ....他说对了 - 你的手指并不在他删掉的任一格子上。接着他再让观众移动手指K2次, 等等. 最后他删得只剩下1个格子,面带微笑地宣布胜利 "我抓到你了!" (鼓掌....).
刚才,大卫尝试着重复这个魔术,不幸的是,他昨天很累,你了解当人在头痛的时候变魔术师十分困难的。你需要编写一个程序来帮助大卫科波菲尔来完成。
【输入】
包括一个整数
【输出】
你的程序应该输出如下的文件:
k1 x1,1 x1,2 …… x1,m1
k2 x2,1 x2,2 …… x2,m2
……
ke xe,1 xe,2 …… xe,me
ki——表示观众们第i次需要移动ki次(N<=ki<=300)每一个ki都是不懂的 xi.1 ~ xi,mi是观众完成第ki次后科波菲尔需要删掉的团的编号,每一轮不能不删图案,每一个图案不能被重复删两次,最后只能留下一个图案
这是一道很奇怪的题目。我想了很久才想到副对角线的做法,然而大神们又给出了更加高明的构造技巧
构造类的好题目
答案可能有很多种,我们需要构造出一组可行解
【方案一】:(奇偶性分析)从样例着手
样例的操作如下
1 2 3
4 5 6
7 8 9
移动3次后 手指不可能落在奇数上,我们可以把最外层的奇数删掉用 * 表示
* 2 *
4 5 6
* 8 *
接着在移动5步,肯定不会落在偶数上面,那么最外层的偶数可以去掉了
就变成了
* * *
* 5 *
* * *
可以自己脑补出来,自己的
这是较为简单的情形,n为偶数的时候稍微复杂一些。
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
(移动5次)
* 2 * 4
5 6 7 *
* 10 11 12
13 * 15 *
(移动7次)
* * * *
* 6 7 *
* 10 11 *
* * * *
变成中间4个数的情况,应该先移动偶数步把7去掉,然后在移动奇数步把6 11 去掉
总结
第奇数次走了奇数步时 将最外层行数+列数为偶数的数字去掉,第偶数次移动奇数步时,将最外层行数+列数为奇数的数字去掉,当n为偶数时,最后剩下的4个数字要特殊处理
额好吧,下面还有各种丧病方案
【方案二】: 染色法(其实这个和方案一的本质是一样的)
我们的方式已确定为第一次让玩家走N步,之后的步数会逐渐增加。
我们把棋盘黑白染色。
易证,走奇数步时会走到另一种颜色上,所以我们只需要每次让玩家走到另一种颜色上去,把相反的颜色的格子删掉。
但是我们不能这么删点,有如下两个问题:
1.如果n一开始为偶数
2.删相反色的格子时候,万一形成了“断路”,把某些玩家孤立在一个地方(你不能让他们剁手)。
首先,第一点很好处理,如果为偶数,则先把周围一圈格子删掉,然后+1,把偶数转换成奇数,继续做。
至于第二点,则是本题的重点,我们需要找到一种切实可行的方法删除格子保证不会出现问题2。
可以脑补一下,像剥皮一样,一圈一圈地删除,那么就能把玩家困在中间某个格子的情形排除了。
具体做法:
(曼哈顿距离)横坐标之差+纵坐标之差
首先,先走n步,把大于与左上角格子曼哈顿距离的点删掉,因为这些格子是达不到的。
然后 如果为偶数 +1 转换成奇数
如果为奇数 +2
设一个dist为每次曼哈顿距离与当前点的差,一层一层向内删除格子,直到dist<=2,玩家已经被困在中间格子内。
【方法三】 高端(wode)构造
按副对角线去掉数字,最后留下1的位置。
副对角线 从左下至右上的数归为副对角线
对于一、二方法有如下代码
#include<cstdio>int n;int main(){ scanf("%d",&n); printf("%d",n); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i-1+j-1>n) printf(" %d",(i-1)*n+j); printf("\n"); int dist=n+2; int now=n; while (dist>2) { now++; while (now%2==0) now++; printf("%d",now); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i+j==dist) printf(" %d",(i-1)*n+j); printf("\n"); dist--; }}
对于方案三 副对角线法又有如下代码
#include <stdio.h>#include <stdlib.h>#define MAX 200int n,i,j,k;void open(){ freopen("109.in","r",stdin); freopen("109.out","w",stdout);}void close(){ fclose(stdin); fclose(stdout);}void init(){ scanf("%d",&n);}void work(){ if (n==2) //特判 { printf("3 4\n5 2 3\n"); } else { printf("%d",k=n); for (i=2;i<n;i++) for (j=n-i+1;j<n;j++) printf(" %d",i*n+j+1); printf("\n%d",k+=1+(n&1)); for (j=0;j<n-1;j++) printf(" %d",n*2+j*(n-1)); for (k+=2,i=n;k<3*n+1;k+=2,i--) { printf("\n%d",k); for (j=0;j<i;j++) printf(" %d",i+j*(n-1));} }}int main(){ open(); init(); work(); close(); return 0;}
- SGU109 各类构造法 【副对角线法】【染色法】
- 染色法
- 康托对角线法
- SGU109
- sgu109
- 交叉染色法
- HDUOJ 4751 染色法
- 环形染色法
- sgu109 Magic of David Copperfield II 构造
- 处女博,《染色法与构造法在棋盘上的应用》的理解
- 方格(带对角线)的走法
- 2015多校第九场 HDU 5402 Travelling Salesman Problem 棋盘染色法,构造
- 【染色法】hdu 3478 Catch
- uva 交叉染色法10004
- 地图染色问题(回溯法)
- 二分图判定(染色法)
- 基于MATLAB的平面度误差对角线法
- 求矩阵的外围元素之和,主对角线元素之和以及副对角线元素之和
- VS2010开发经验问题收集整理
- The connection to adb is down, and a severe error has occured(Android模拟器端口被占用)
- DNS扫盲系列之五:域名配置ZONE文件
- Android编程获取手机型号,本机电话号码,sdk版本及firmware版本号(即系统版本号)
- 仿QQ控件图片下拉放大效果
- SGU109 各类构造法 【副对角线法】【染色法】
- DNS扫盲系列之六:擅用日志排除BIND故障
- 安装xampp后apache不能启动解决方法
- SSH框架中各个XML文件的作用
- 【写在首篇】会走到哪,只有这样写下去才知道
- DNS扫盲系列之七:关注域名安全
- 替换输入字符串中的危险字符
- 重载函数模板 友元运算符时出现无法解析问题
- sdutoj3009 幸运数