USACOTrainning.Checker Challenge
2010-04-15 22:07
381 查看
这道题花了很多的时间额。。。
大意是九皇后。
USACO给出的Hint很强大,但自己下还是TLE在最后一个数据上,时间消耗1.3s左右,方法就是普通的标记数组表示不能访问。
弄反斜线的坐标和索引对应时掣肘了那么几下。。。
后来看到有人说位运算,就把之前的标记数组改成了二进制状态表示,但效果一点都没有,左右是一样,代码里面还是要For那些点来判断。
就按Hint里的把多次调用的小代码放到主体中,因为大量的Call也会造成nontrial的消耗,但未果。
至于Hint里说的对称和旋转重复的部分不去跑,可以省掉不少时间,可是不会。
看了大牛们的Blog后,才知道如下:
用3个数组来表示3种情况下对应的某行的状态,然后每次都获得一个数,表示出那些位置是可以访问的,用t&(-t)的办法,可以获得最低位的1,每次的提取就省掉了没用的For了,还有用到^操作,是练习位运算的一道好题。
用了如下的位运算操作AC如下:
又有一大牛这样说,n分奇数和偶数,偶数时,第一行枚举前半段,这样求的的解一定可以在右边找到镜像。奇数时,分别枚举中间的行和列,要求都小于一般,且规定行小于列,这样可以保证旋转+镜像后的解不重复且这些解就是最终的解,只有1/8的原来的个数。
介于实现考虑,都用对称,省掉一半的时间,n=6时特判。
AC如下:
到Chapter 2了,兴奋。
感谢:
http://blog.sina.com.cn/s/blog_5ed6a69f0100dywr.html
http://jingsixee.blog.hexun.com/4915336_d.html
大意是九皇后。
USACO给出的Hint很强大,但自己下还是TLE在最后一个数据上,时间消耗1.3s左右,方法就是普通的标记数组表示不能访问。
弄反斜线的坐标和索引对应时掣肘了那么几下。。。
后来看到有人说位运算,就把之前的标记数组改成了二进制状态表示,但效果一点都没有,左右是一样,代码里面还是要For那些点来判断。
就按Hint里的把多次调用的小代码放到主体中,因为大量的Call也会造成nontrial的消耗,但未果。
至于Hint里说的对称和旋转重复的部分不去跑,可以省掉不少时间,可是不会。
看了大牛们的Blog后,才知道如下:
用3个数组来表示3种情况下对应的某行的状态,然后每次都获得一个数,表示出那些位置是可以访问的,用t&(-t)的办法,可以获得最低位的1,每次的提取就省掉了没用的For了,还有用到^操作,是练习位运算的一道好题。
用了如下的位运算操作AC如下:
又有一大牛这样说,n分奇数和偶数,偶数时,第一行枚举前半段,这样求的的解一定可以在右边找到镜像。奇数时,分别枚举中间的行和列,要求都小于一般,且规定行小于列,这样可以保证旋转+镜像后的解不重复且这些解就是最终的解,只有1/8的原来的个数。
介于实现考虑,都用对称,省掉一半的时间,n=6时特判。
AC如下:
到Chapter 2了,兴奋。
#include <iostream> #include <string> #include <algorithm> #include <string.h> #include <vector> #include <math.h> #include <time.h> #include <queue> #include <set> using namespace std; const int MAX = 15; int n, cnt, ansCnt; int full; //表示都能放1111..n int limit; //表示优化对称用的 int stateCol[MAX]; int stateA[MAX]; //A为主对角线 int stateB[MAX]; //B为从对角线 int ans[MAX]; //表示棋盘中每行的各种方法的状态 //1表示不能放 void ready() { memset(stateCol, 0, sizeof(stateCol)); memset(stateA, 0, sizeof(stateA)); memset(stateB, 0, sizeof(stateB)); full = (1 << n) - 1; limit = (1 << ((n + 1) / 2)) - 1; cnt = 0; ansCnt = 0; } int getBit(int x) { int res = 0; while(x) { x >>= 1; res++; } return res; } void dfs(int row, int t) { if(row == n) { cnt++; if(cnt <= 3) { for(int i = 0; i < n; i++) { if(i == 0) printf("%d", ans[i]); else printf(" %d", ans[i]); } printf("\n"); } ansCnt++; if(n > 6 && ans[0] <= n / 2) ansCnt++; return; } //先取出能放的状态,can表示能放的位置 int can = t ^ (stateCol[row] | stateA[row] | stateB[row]); while(can) { int col = (can & (~can + 1)); //取最后的一位1,按顺序遍历 ans[row] = getBit(col); stateCol[row + 1] = stateCol[row] | col; stateA[row + 1] = ((stateA[row] | col) << 1) & full; stateB[row + 1] = (stateB[row] | col) >> 1; dfs(row + 1, full); can ^= col; } } void go() { if(n > 6) dfs(0, limit); else dfs(0, full); printf("%d\n", ansCnt); } int main() { //freopen("checker.in", "r", stdin); //freopen("checker.out", "w", stdout); scanf("%d", &n); ready(); go(); }
感谢:
http://blog.sina.com.cn/s/blog_5ed6a69f0100dywr.html
http://jingsixee.blog.hexun.com/4915336_d.html
相关文章推荐
- USACO 1.5 Checker Challenge (checker)
- 【搜索】【USACO】Checker Challenge
- [USACO 1.5.4] Checker Challenge
- USACO 1.5.4 Checker Challenge 题解
- USACO 1.4 Checker Challenge 位运算
- USACO 1.5.4 Checker Challenge ———— DFS
- USACO1.5.4 checker challenge
- USACO 1.5 Checker Challenge
- USACO 1.5 Checker Challenge (位操作)
- USACO6.5.5 Checker Challenge( checker)
- USACO 6.5.5 Checker Challenge 回溯
- There are 常数s 和 常数s! Usaco 1.5.4 Checker Challenge
- [usaco]1.5 Checker Challenge
- USACO:Checker Challenge
- USACO Checker Challenge
- USACO 6.5 Checker Challenge
- usaco Section 1.5 Checker Challenge 最慢0.162秒0.0+n皇后问题位运算版(C语言)
- USACO section 1.5 Checker Challenge(dfs深搜)
- USACO sec1.5 Checker Challenge
- usaco6.5.5 Checker Challenge