• 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

  • 相关阅读:
    不用服务器也能跑的框架wojilu
    PLI 到 COBOL 的转换数据类型 【不搞Mainframe的可能看不懂,冷门的语言】
    我记录网站综合系统 技术原理解析[8:ActionChecker流程]
    纪念VB.NET君
    我记录网站综合系统 技术原理解析[7:CSS类]
    我记录网站综合系统 技术原理解析[10:PermissionChecker流程]
    我记录网站综合系统 技术原理解析[6:内容初始化处理]
    我记录网站综合系统 技术原理解析[9:HttpMethodChecker流程]
    怎么打败腾讯[纯讨论]
    VisualStudio2012新特性[路边社通稿]
  • 原文地址:https://www.cnblogs.com/litstrong/p/1712983.html
Copyright © 2020-2023  润新知