题目链接:​​这里​

柱爷有天上课无聊,于是和同桌卿学姐一起下一种奇特的棋:

棋盘如图:

title

在开始游戏前,棋盘上已经放好了一些边,然后柱爷先手,开始在棋盘上没有边的位置添加一条边上去

如果添加边后围成一个三角形则获得一分(对于棋盘上游戏开始前已经围好了的三角形,两个人都不得分)并且下一轮还该他!否则下一轮该另一个人。

如果两个人都以最优策略下棋,那么柱爷能赢么?

注:只算最小的三角形!(三个边围成的三角形)

如果能赢输出“WIN!”

必败输出“LOSE!”

平局输出“Draw”

(都不输出引号)

愚人王感觉这规则太抽象了,都没人赶预测柱爷能不能赢了,于是画了个图解释了下题意:

title

对应: 5 1 2 3 4 5 的情况,如果这是开局情况,那么此时两个人都是0分,改柱爷先下,

如果他在6的位置填一条边,那么4,5,6将围城一个小三角形,柱爷得一分。接下来还是改柱爷下棋。

如果他在18的位置填一条边,那么将无法构成三角形,柱爷不得分,接下来改卿学姐下棋。

一直这样,直到填完所有边后,游戏结束。此时分高的人获胜,分相同则平局。

Input

第一行一个正整数n,表示开始游戏前有多少条边已经被放上去了。

第二行有n个正整数,a1…an代表已经放好的边的编号。

1<=a1…an<=18

Output

一行,输出柱爷的结局。

如果能赢输出“WIN!”

必败输出“LOSE!”

平局输出“Draw”

6

1 2 3 4 5 6

WIN!

5

4 5 6 7 8

LOSE!

//CDOJ 1402

#include <bits/stdc++.h>
using namespace std;
int dp[1<<20][2]; //dp[i][0]表示i这个状态柱爷的最大得分,dp[i][1]表示i这个状态卿学姐的最大得分
int viss[1<<20][2];
int vis[30];
int cal(int x){//计算状态x没构成三角形的虚线三角形的个数
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= 18; i++)
if((x>>i)&1) vis[i] = 1;
int ans = 0;
for(int i = 0; i < 6; i++){
if(vis[3*i+1]&&vis[3*i+2]&&vis[3*i+3]) ans++;
}
if(vis[3]&&vis[5]&&vis[7]) ans++;
if(vis[6]&&vis[11]&&vis[13]) ans++;
if(vis[9]&&vis[14]&&vis[16]) ans++;
return 9-ans;
}
int dfs(int now, int flag){
if(viss[now][flag]) return dp[now][flag];
viss[now][flag] = 1;
int last = cal(now);
for(int i = 1; i <= 18; i++){
if(((now>>i)&1)==0){
int nxt = now|(1<<i);
int num = last - cal(nxt);
if(num > 0){//柱爷可以继续
dp[now][flag] = max(dp[now][flag], dfs(nxt, flag)+num);
}
else{//换卿学姐
dp[now][flag] = max(dp[now][flag], last - dfs(nxt, 1-flag));
}
}
}
return dp[now][flag];
}
int main(){
int n, now = 0;
scanf("%d", &n);
while(n--){
int x; scanf("%d", &x); now |= (1<<x);
}
int last = cal(now);
int a = dfs(now, 0);
int b = last - a;
if(a > b) puts("WIN!");
else if(a < b) puts("LOSE!");
else puts("Draw");
return 0;
}