P2361 yyy棋 题解

· · 题解

题目描述:

P2361题目传送门

算法思路:

一道必胜策略好题。

应对方法:

须知:以下式子中 A 为长, B 为宽。

  1. 如果有中心点,己方先手,下中心点。

(通俗讲,如果长宽都是奇数,自己先手下 (A/2+1,B/2+1) 位置)

  1. 下对手中心对称的位置,举个例子,如果对手下 (x,y),我们就下在 (A-x+1,B-y+1)

(通俗讲,粘着对手下!

位置问题解决了,但是颜色该怎么办呢?

1. 考虑长宽都是奇数:

奇数不会出现 (x,y)(A-x+1,B-y+1) 旁边,所以下的颜色跟对手一样。

2. 考虑长或宽有偶数:

偶数会出现 (x,y)(A-x+1,B-y+1) 旁边,所以反着对手的颜色下。

(举个例子,A=3,B=2,x=2,y=1,要下的是:(2,2),在对手下面)

蒟蒻のAC代码

AC记录

#include <bits/stdc++.h>
using namespace std;
int a,b;
struct node
{
    bool is_full=0;//有没有被下过
    int color=-1;//什么颜色
    bool can_be_1=1;//可以下黑棋
    bool can_be_0=1;//可以下白棋
}f[10][10];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void out()
{
    cout<<"Buwanle";
    exit(0);
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>a>>b;
    int t=0,flag=1;
    if(a%2)t++;
    if(b%2)t++;
   //t作用是看长宽是否都是奇数
    if(t==2)cout<<"First";
    else
    {
        cout<<"Second";
        flag=0;
    }
    cout<<'\n';
    if(t==2)
    {
    //都是奇数的话先手,下中心点
        cout<<a/2+1<<' '<<b/2+1<<' '<<1<<'\n';
        for(int i=0;i<4;i++)
        {
            int tx=dx[i]+a/2+1;
            int ty=dy[i]+b/2+1;
            if(tx<1||ty<1||tx>a||ty>b)continue;
            f[tx][ty].can_be_1=0;
        }
    }
    int x,y,c;
    while(cin>>x>>y>>c)
    {

        if(f[x][y].is_full)out();//已被下过
        if(c==1&&f[x][y].can_be_1==0)out();//不可以下黑棋却下黑棋
        if(c==0&&f[x][y].can_be_0==0)out();//不可以下白棋却下白棋
        f[x][y].is_full=1;
        f[x][y].color=c;
        for(int i=0;i<4;i++)
        {
            int tx=dx[i]+x;
            int ty=dy[i]+y;
            if(tx<1||ty<1||tx>a||ty>b)continue;
            if(c==1)f[tx][ty].can_be_1=0;
            else f[tx][ty].can_be_0=0;
        }//给上下左右附上不可以下同样颜色
        int will_color=c;
        if(!flag)
        {
            if(c==1)will_color=0;
            else will_color=1;
        }//看需要下什么颜色
        int will_choose_x=a-x+1;
        int will_choose_y=b-y+1;
        //中心对称
        cout<<will_choose_x<<' '<<will_choose_y<<' '<<will_color<<'\n';
            //粘着对手下
        for(int i=0;i<4;i++)
        {
            int tx=dx[i]+will_choose_x;
            int ty=dy[i]+will_choose_y;
            if(tx<1||ty<1||tx>a||ty>b)continue;
            if(will_color==1)f[tx][ty].can_be_1=0;
            else f[tx][ty].can_be_0=0;
        }//给上下左右附上不可以下同样颜色
    }
    return 0;
}

总结:

遇事不决,小学数学!