SOS Gym - 101775L (找规律)

版权声明:如有错误,请指出,不胜感激。 https://blog.csdn.net/qq_36424540/article/details/82910289

Mr. Panda and Mr. Sheep are playing a game on a 1 × N game board. Initially, all the cells are empty. Mr. Panda and Mr. Sheep take alternate moves and Mr.Panda moves first.

On each move, a player must fill an 'S' or 'O' into an empty cell. After the move, if there are 3 consecutive cells from left to right form the word "SOS", the player wins the game and the game finished.

If the board gets filled up without SOS appearing consecutively, no one wins the game, the game end with draw.

Now, if both Mr. Panda and Mr. Sheep play optimally, find out the result of the game.

Input

The first line of the input gives the number of test cases, T. T test cases follow.

Each test case contains one line consists of one number N, indicating the size of the game board.

  • 1 ≤ T ≤ 1000.
  • 1 ≤ N ≤ 1000.

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the game result if both players play optimally. "Panda" for Mr. Panda winning the game, "Sheep" for Mr. Sheep winning the game, "Draw" for draw game.

Example

Input

2
3
7

Output

Case #1: Draw
Case #2: Panda

Note

In the first test case, as there are only 3 cells, both players cannot win as Mr. Sheep only has one move and after his move, there is still one cell left empty. So Mr. Sheep is impossible to win, but it's easy for him to avoid Mr. Panda to win. He can either fill 'O' in the first or third cell, or fill 'S' in the second cell to make it a draw game.

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=b-1;i>=a;--i)


int main()
{
	int T;
	scanf("%d",&T);
	rep(kase,0,T){
		int n;
		scanf("%d",&n);
		printf("Case #%d: ",kase+1);

		if(n<7)printf("Draw\n");
		else if(n>=7&&n<16){
			if(n&1)printf("Panda\n");
			else printf("Draw\n");
		}
		else{
			if(n&1)printf("Panda\n");
			else printf("Sheep\n");
		}
	}
    return 0;
}

打表

#include<bits/stdc++.h>//打表
using namespace std;
typedef unsigned long long ll;
const int INF=0x3f;
char dp[500000000000];//这个记忆化是给当前的n用的
int a[110];
ll get_s(int n){
    ll s=0;
    for(int i=1; i<=n; i++) s=s*3+a[i];//这个状态是唯一的,但是后面不同的枚举可能会重复用到这个状态
    return s;
}
bool check(int n){
    for(int i=3; i<=n; i++)
        if(a[i]==1 && a[i-1]==2 && a[i-2]==1)
            return true;
    return false;
}
void show(int n){
    for(int i=1; i<=n; i++)
        printf("%d ", a[i]);
    puts("");
}
int dfs(int n,int cnt){
	//show(cnt);
    ll s=get_s(n);//当前棋盘的状态
    char &ret=dp[s];
    if(ret^INF)	return ret;
    if(check(n)) return ret=-1;
    if(cnt==n) return ret=0;
    bool ok=true;
    for(int i=1; i<=n; i++){//当前这个位置下1/2, 那么枚举之后就是这个点什么都不下了,就会去枚举后面了
        if(a[i]==0){
            for(int j=1; j<=2; j++){
                a[i]=j;
                int t=dfs(n, cnt+1);
                a[i]=0;
                if(t==-1) return ret=1;//后面存在必败态,一定是胜利的
                if(t==0) ok=false;//后面没有必败态,还有平局
            }
        }
    }
    return ret=ok?-1:0;//可能平局都没有
}

int main(){
    for(int i=1;i<30; i++){
		memset(dp, 0x3f, sizeof dp);
        memset(a, 0, sizeof a);
        printf("%d: %d\n", i, dfs(i, 0));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/82910289
SOS