usaco 1.5.4——checker

Checker Challenge 跳棋的挑战

描述

检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列只有一个,每条对角线(包括两条主对角线的所有对角线)上至多有一个棋子。

图见usaco原图

上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:

行号 1 2 3 4 5 6 
列号 2 4 6 1 3 5 

这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出,这是作弊。如果你坚持作弊,那么你登陆USACO Training的帐号将被无警告删除

格式

PROGRAM NAME: checker

INPUT FORMAT:

(checker.in)

一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。

OUTPUT FORMAT:

(checker.out)

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

SAMPLE INPUT

6 

SAMPLE OUTPUT

2 4 6 1 3 5 
3 6 2 5 1 4 
4 1 5 2 6 3 
4

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 276 KB]
   Test 2: TEST OK [0.000 secs, 276 KB]
   Test 3: TEST OK [0.000 secs, 276 KB]
   Test 4: TEST OK [0.000 secs, 276 KB]
   Test 5: TEST OK [0.000 secs, 276 KB]
   Test 6: TEST OK [0.000 secs, 276 KB]
   Test 7: TEST OK [0.054 secs, 276 KB]
   Test 8: TEST OK [0.162 secs, 276 KB]

All tests OK.

Your program ('checker') produced all correct answers! This is your submission #4 for this problem. Congratulations!

 

分析:

额。比较经典的N皇后问题

让我灰常郁闷啊。

开始打的裸dfs,

结果最后一个点超时,

我尝试了好多剪枝和优化,

都不大管用,

在网上看的方法都不大懂,

尤其是那个对称的优化,最让我无语了。。。

于是我采用位运算的方法来计算方案数,

位运算部分完全参考M67牛的文章,

基本没有变化,具体原理说不清。。。

位运算部分参考M67牛的

http://www.matrix67.com/blog/archives/266

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{
ID: codeway3
PROG: checker
LANG: PASCAL
}
program checker;
  type
    ll=array[1..15,1..15]of integer;
  var
    i,j,n,bb,m,k,l,js:longint;
    a:ll;
    b:array[1..13]of longint;
  procedure doing(x,y:longint;aa:ll);
    var
      i,j:longint;
    begin
      if m>3 then exit;
      for i:=1 to n do
        begin
          aa[x,i]:=1;
          aa[i,y]:=1;
          if i+y-x in [1..n] then aa[i,i+y-x]:=1;
          if x+y-i in [1..n] then aa[i,x+y-i]:=1;
        end;
      b[x]:=y;
      if x=n then
        begin
          if m<3 then
            begin
              for i:=1 to n-1 do write(b[i],' ');
              writeln(b[n]);
            end;
          inc(m);
          b[x]:=0;
          exit;
        end;
      for i:=1 to n do
        if aa[x+1,i]=0 then doing(x+1,i,aa);
      b[x]:=0;
    end;
 
  procedure test(row,ld,rd:longint);
    var
      pos,p:longint;
    begin
      if row<>js then
        begin
          pos:=js and not (row or ld or rd);
          while pos<>0 do
            begin
              p:=pos and -pos;
              pos:=pos-p;
              test(row+p,(ld+p)<<1,(rd+p)>>1);
            end;
        end
      else inc(m);
    end;
 
  begin
    assign(input,'checker.in');
    reset(input);
    assign(output,'checker.out');
    rewrite(output);
    readln(n);
    m:=0;
    for i:=1 to do doing(1,i,a);
    m:=0;
    js:=(1<<n)-1;
    test(0,0,0);
    writeln(m);
    close(input);
    close(output);
  end.

posted on   codeway3  阅读(334)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

< 2011年10月 >
25 26 27 28 29 30 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示