USACOTrainning.Checker Challenge

这道题花了很多的时间额。。。

大意是九皇后。

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了,兴奋。

1 #include <iostream>
2 #include <string>
3 #include <algorithm>
4 #include <string.h>
5 #include <vector>
6 #include <math.h>
7 #include <time.h>
8 #include <queue>
9 #include <set>
10  using namespace std;
11
12  const int MAX = 15;
13
14  int n, cnt, ansCnt;
15 int full; //表示都能放1111..n
16 int limit; //表示优化对称用的
17 int stateCol[MAX];
18 int stateA[MAX]; //A为主对角线
19 int stateB[MAX]; //B为从对角线
20 int ans[MAX];
21 //表示棋盘中每行的各种方法的状态
22 //1表示不能放
23
24 void ready()
25 {
26 memset(stateCol, 0, sizeof(stateCol));
27 memset(stateA, 0, sizeof(stateA));
28 memset(stateB, 0, sizeof(stateB));
29 full = (1 << n) - 1;
30 limit = (1 << ((n + 1) / 2)) - 1;
31 cnt = 0;
32 ansCnt = 0;
33 }
34
35 int getBit(int x)
36 {
37 int res = 0;
38 while(x)
39 {
40 x >>= 1;
41 res++;
42 }
43 return res;
44 }
45
46 void dfs(int row, int t)
47 {
48 if(row == n)
49 {
50 cnt++;
51 if(cnt <= 3)
52 {
53 for(int i = 0; i < n; i++)
54 {
55 if(i == 0) printf("%d", ans[i]);
56 else printf(" %d", ans[i]);
57 }
58 printf("\n");
59 }
60 ansCnt++;
61 if(n > 6 && ans[0] <= n / 2) ansCnt++;
62 return;
63 }
64 //先取出能放的状态,can表示能放的位置
65 int can = t ^ (stateCol[row] | stateA[row] | stateB[row]);
66 while(can)
67 {
68 int col = (can & (~can + 1)); //取最后的一位1,按顺序遍历
69 ans[row] = getBit(col);
70 stateCol[row + 1] = stateCol[row] | col;
71 stateA[row + 1] = ((stateA[row] | col) << 1) & full;
72 stateB[row + 1] = (stateB[row] | col) >> 1;
73 dfs(row + 1, full);
74 can ^= col;
75 }
76 }
77
78 void go()
79 {
80 if(n > 6) dfs(0, limit);
81 else dfs(0, full);
82 printf("%d\n", ansCnt);
83 }
84
85 int main()
86 {
87 //freopen("checker.in", "r", stdin);
88 //freopen("checker.out", "w", stdout);
89
90 scanf("%d", &n);
91 ready();
92 go();
93 }

 

感谢:

http://blog.sina.com.cn/s/blog_5ed6a69f0100dywr.html

http://jingsixee.blog.hexun.com/4915336_d.html

posted @ 2010-04-15 22:07  litstrong  阅读(253)  评论(0编辑  收藏  举报