NOIP 模擬題 國際跳棋

B 國際跳棋
文件名 輸入文件 輸出文件 時間限制 空間限制
chess.cpp/c/pas chess.in chess.out 1s 512MB

題目描述
國際跳棋是一種古老的棋類遊戲,遠在古埃及法老時期就已存在,現代國際跳
棋是在 12 世紀定型的。國際跳棋是由各國的民族跳棋演變而來,其歷史源遠流長。
簡化版(與標準國際跳棋略有差別)國際跳棋規則:
• 國際跳棋的棋盤由 10 × 10 共 100 個格子組成
• 初始的時候,黑白雙方各有 20 個棋子
• 移動:可以將我方任意棋子向左前方或右前方移動 1 步
• 跳喫:只要左前方、右前方、左後方、右後方相鄰格子有對方棋子,且跳過這
枚對方棋子後有空位,則可以跳過對方棋子並將對方棋子喫掉。如你的棋子在
(x,y), 對方棋子在 (x+1,y+1), (x+2,y+2) 爲空, 則你可以跳到 (x+2,y+2)
並喫掉對方的棋子
• 加冕: 任何一個棋子在行動過程停止的時候停到了對方底線(最靠近對方的一
行)就可以加冕,從此成爲“王”。注意,連續跳喫的時候只有最後一步停在對
方底線纔可以加冕
• 連跳:跳喫可以由多次跳喫組成。
• 王的特權:王在移動的時候可以無視方向(左前、右前、左後、右後都可以) ,
無視距離(走幾步都行, 直到遇到別的棋子) , 無視跳喫距離(比如說 (x,y) 跳
過 (x + 3,y + 3) 落到 (x + 7,y + 7) 是可以的,但是這中間除了有被喫掉的對
方棋子,不能有其他棋子
• 在跳喫結束的時候纔將被喫掉的棋子拿出棋盤,在這之前作爲“屏障”,即這些
棋子不能再次被跳喫,也不能落子
• 按照以上規則,給定一個棋局,合法的操作方案有很多。然而,每次必須選擇
喫子最多的操作方案。比如,在某種棋局下,有 A、B、C、D 四種方案,A、
B 喫子 3 枚,C 喫 1 枚,D 喫 0 枚,則真正合法的操作總數爲 2
作爲一個國際跳棋迷,陶陶想要編寫一個網絡對戰跳棋軟件。然而他現在不會
判斷怎樣的操作是合法的。對於給定的局面,你能給出所有合法的操作嗎?

輸入格式
輸入數據是兩個十行十列的矩陣,第一個矩陣中的每個點可能是以下三種:
• 0 空位置
• 1 我方棋子
• 2 對方棋子
第二個矩陣描述的是國王的情況。若爲 1,表示是國王;爲 0 表示不是國王。
輸出格式
輸出第一行爲一個數字,表示合法操作的個數 ans。
下面一共 ans 行,每行表示一種合法操作中被操作的棋子。格式爲 (x,y) 表示
該棋子在第 x 行、第 y 列(注意,逗號後面沒有空格) 。如果某一個棋子有多種合
法操作,則輸出多遍。輸出的順序按從上到下、從左到右。
如果沒有任何合法操作,只輸出一個 0 即可

樣例輸入 1
0000000000
0000100000
0000000200
0000100000
0000000200
0000001000
0000000200
2000000000
0101000200
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
5
0000000000
0000000000
0000000000
0000000000

樣例輸出 1
2
(6,7)
(6,7)

讀題很重要,讀懂了差不多就會了

gty:“這道題目的難點不在搜索也不在剪枝,在讀題和實現”

考試時沒有讀懂題。

那麼我在這裏先強調一下:這道題加冕什麼的鬼東西都沒有用;我們求的方案是操作的棋子只跳一步(連跳算一步)。

就是簡(ma)單(fan)的搜索。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdlib>
using namespace std;
int King[15][15],map[15][15];
int wx[100009],wy[100009],cnt;
int maxn;//表示喫掉的最大個數 
bool die[15][15];
int dx[]={1,1,-1,-1},dy[]={1,-1,1,-1}; 
void dfs1(int x,int y,int num,int sx,int sy)
{
    if(num>=maxn)
    {
        if(num>maxn) maxn=num,cnt=0;
        wx[++cnt]=sx;
        wy[cnt]=sy;
    }
    for(int i=0;i<4;i++)
    {
        int xx=x+dx[i],yy=y+dy[i];
        if(map[xx][yy]==2&&(!die[xx][yy])&&map[xx+dx[i]][yy+dy[i]]==0&&xx+dx[i]<=10&&xx+dx[i]>=1&&yy+dy[i]>=1&&yy+dy[i]<=10)
         die[xx][yy]=1,dfs1(xx+dx[i],yy+dy[i],num+1,sx,sy),die[xx][yy]=0; 
    }
}
void dfs2(int x,int y,int num,int sx,int sy)
{
    if(num>=maxn)
    {
        if(num>maxn) maxn=num,cnt=0;
        wx[++cnt]=sx;
        wy[cnt]=sy;
    }

    int xx,yy,XX,YY;
    for(xx=x+1,yy=y+1;xx<=10&&yy<=10;xx++,yy++)//右下 
    {
        if(map[xx][yy]==2&&!die[xx][yy])
        {
            for(XX=xx+1,YY=yy+1;XX<=10&&YY<=10;XX++,YY++)
            {
                if(map[XX][YY]==0)
                die[xx][yy]=1,dfs2(XX,YY,num+1,sx,sy),die[xx][yy]=0;
                else break;
            }
        }
    }

    for(xx=x-1,yy=y+1;xx>=1&&yy<=10;xx--,yy++)//右上 
    {
        if(map[xx][yy]==2&&!die[xx][yy])
        {
            for(XX=xx-1,YY=yy+1;XX>=1&&YY<=10;XX--,YY++)
            {
                if(map[XX][YY]==0)
                die[xx][yy]=1,dfs2(XX,YY,num+1,sx,sy),die[xx][yy]=0;
                else break;
            }
        }
    }

    for(xx=x+1,yy=y-1;xx<=10&&yy>=1;xx++,yy--)//左下 
    {
        if(map[xx][yy]==2&&!die[xx][yy])
        {
            for(XX=xx+1,YY=yy-1;XX<=10&&YY>=1;XX++,YY--)
            {
                if(map[XX][YY]==0)
                die[xx][yy]=1,dfs2(XX,YY,num+1,sx,sy),die[xx][yy]=0;
                else break;
            }
        }
    }

    for(xx=x-1,yy=y-1;xx>=1&&yy>=1;xx--,yy--)//左上 
    {
        if(map[xx][yy]==2&&!die[xx][yy])
        {
            for(XX=xx-1,YY=yy-1;XX>=1&&YY>=1;XX--,YY--)
            {
                if(map[XX][YY]==0)
                die[xx][yy]=1,dfs2(XX,YY,num+1,sx,sy),die[xx][yy]=0;
                else break;
            }
        }
    }
}
void get_ans()
{
    for(int i=1;i<=10;i++)
     for(int j=1;j<=10;j++)
      if(map[i][j]==1) 
       if(!King[i][j]) dfs1(i,j,0,i,j);//普通棋子 
       else dfs2(i,j,0,i,j);//王棋 
    if(maxn==0)
    {
        cnt=0;
        for(int i=1;i<=10;i++)
          for(int j=1;j<=10;j++)
            if(map[i][j]==1){
            if(!King[i][j])
            {
                for(int k=2;k<4;k++)
                {
                    int x=i+dx[k],y=j+dy[k];
                    if(!map[x][y]&&x<=10&&x>=1&&y<=10&&y>=1)//這個地方也要判斷越界,掉下會WA的
                    wx[++cnt]=i,wy[cnt]=j;
                }
            }
            else
            {
                for(int k=0;k<4;k++)
                {
                    for(int p=1;p<=10;p++)
                    {
                        int x=i+dx[k]*p,y=j+dy[k]*p;
                        if(x>10||x<1||y>10||y<1) break;
                        if(map[x][y]) break;
                        wx[++cnt]=i,wy[cnt]=j;
                    }
                }
            }
        }
    }
} 
int main()
{
    freopen("chess.in","r",stdin);
    freopen("chess.out","w",stdout);
    for(int i=1;i<=10;i++)
    for(int j=1;j<=10;j++)
    {
        char c;cin>>c;
        map[i][j]=c-'0';
    }
    for(int i=1;i<=10;i++)
    for(int j=1;j<=10;j++)
    {
        char c;cin>>c;
        King[i][j]=c-'0'; 
    }
    get_ans();

    printf("%d\n",cnt);
    for(int i=1;i<=cnt;i++)
     printf("(%d,%d)\n",wx[i],wy[i]);
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章