[位运算+搜索]下棋

[题目描述]

【问题描述】

 

学习之余,小秋秋还喜欢进行棋类活动。。。

现在,小秋秋迷上了一个叫tic-tac-toe的游戏。。(这种诡异的名字?原题如此)。

这个游戏是两个人轮流在4*4的格子中放棋子,一个人放满了一行或一列或一个对角线就算赢。

现在,小秋秋用X先手,已经下过许多步了。他想知道自己现在是否有必胜策略,以及最小的字典序走法。

 

【输入文件】

 

输入有多组数据。

需要你求的数据以’?’开头,然后是一个4*4的矩阵,’.’代表空,’x’代表小秋秋的棋子,’o’代表小秋秋对手的棋子。

输入文件以’$’结束。

 

【输出文件】

 

对于每组数据输出一行,若有必胜策略,输出(x,y)表示字典序最小的走法是下到(x,y)(0<=x,y<4)。若无必胜策略,输出#####

 [题解]

        这道题是一道红果果的搜索题= =.

        很简单的最大最小剪枝,我用位运算把棋盘压到一个longint里了.

        hi函数是system库的标准函数,返回值是输入的二进制的前半部分.

        附上我冗长的代码= =:


program chess;
type
        int=longint;
        board=int;
var
        i,j,m,n,nx,np:int;
        k:board;
        a,b,aa,c:array[1..16]of int;
        ch:char;
        ok:boolean;
        st:string;

procedure push(var p:board;ch:char;x:int);
begin
        if ch='.'then exit;
        if upcase(ch)='X'then begin p:=p or(a[x]);inc(nx);end
                else begin p:=p or(b[x]);inc(np);end;
end;

function dfs(p:board;x:int;q:int):int;var i,j:int;k:int=0;//true==q win
begin
        if(hi(p)+lo(p)=1<<16-1)then exit(-1);
        for i:=1 to 10 do begin
                if aa[i]and p=aa[i]then exit(0);
                if aa[i]and hi(p)=aa[i]then exit(0);
        end;
        for i:=1 to 16 do if(p and c[i]=0)then begin
                if q=1 then j:=dfs(p+a[i],i,0)else j:=dfs(p+b[i],i,1);
                if j=0 then exit(1);if j=-1 then k:=-1;
        end;
        exit(k);
end;

begin
        assign(input,'chess.in');reset(input);
        assign(output,'chess.out');rewrite(output);
        for i:=1 to 16 do begin a[i]:=1<<(i-1);b[i]:=a[i]<<16;c[i]:=a[i]or b[i];end;
        for i:=1 to 4 do aa[i]:=(1<<4-1)<<(4*(i-1));
        for i:=1 to 4 do aa[5]:=aa[5]or a[i*4];
        for i:=6 to 8 do aa[i]:=aa[i-1]>>1;
        for i:=1 to 4 do begin
                aa[9]:=aa[9]or a[(i-1)<<2+i];
                aa[10]:=aa[10]or a[i*4-4+(4-i+1)];
        end;
        while not seekeof do begin
                readln(ch);k:=0;ok:=false;nx:=0;np:=0;
                if ch='$'then break;
                for i:=1 to 4 do begin
                        for j:=1 to 4 do begin
                                read(ch);push(k,ch,4*(i-1)+j);
                        end;
                        readln;
                end;
                if(nx<4)or(np<4)then begin
                        writeln('#####');
                        continue;
                end;
                for i:=1 to 16 do if(c[i]and k=0)and(dfs(k+a[i],i,0)=0)then begin
                        if i and 3=0 then j:=3 else j:=i and 3-1;
                        writeln('(',(i-1)div 4,',',j,')');ok:=true;
                        break;
                end;
                if not ok then writeln('#####');
        end;
        close(input);close(output);
end.

        被0和1绕晕了.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值