https://codeforc.es/gym/101775/problem/L
题意
Panda和Sheep在一个1×n的矩阵中填字母S或O,当一个人填出SOS时获胜。
题解
博是博不出来的,只能靠打表维持生计。
打表也涉及到了博弈的思想。这里需要理解先手必胜态和先手必败态的概念。
先手必胜态 : 当且仅当即后有一个先手必败态。
先手必败态:当且仅当其后全是先手必胜态。
通俗的解释:
如果当前是必胜态,那么当前就有办法走到一个后手必败的状态。
如果当前是必败态,那么无论怎么走,后手都是必胜的状态。
因此打表就是暴力枚举每一种状态,从而推出先手是什么态。
对于一个状态st,
如果其后继状态中有一个满足SOS(此时相对于先手是必败态,因为先手无法操作),那么其就为必胜态。
如果后继状态中有没有满足SOS的但是有平局,那么先手肯定选择平局。
如果后继状态既没有SOS也无平局,那说明后继状态都是必胜态,那此时就是必败态。
打表代码
#include <unordered_map>
#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e8+10;
int a[maxn];
int n;
const int mod = 1e8+7;
unordered_map<ll,int> mp;
bool judge() {
for(int i = 1; i+2 <= n; ++i)
if(a[i] == 1 && a[i+1] == 2 && a[i+2] == 1)
return true;
return false;
}
ll f() {
ll t = 0;
for(int i = 1; i <= n; ++i)
t = t*10+a[i];
return t;
}
// SOS 对于先手是必败态,因为先手无法操作
// -1 失败,2平局,1胜利
int dfs(int cnt) {
ll st = f();
if(judge())
return -1; // 当前状态是先手必败态,即先手无法操作
if(cnt == n+1)
return 2; // 平局
if(mp[st] != 0) return mp[st];
bool flag = true;
int t;
for(int i = 1; i <= n; ++i) {
if(a[i]) continue;
for(int j = 1; j <= 2; ++j) {
a[i] = j;
t = dfs(cnt+1); // 采集下一步的信息
a[i] = 0;
if(t == -1) { // 发现一个必败态,那么先手一定是必胜态
return mp[st] = 1;
}
if(t == 2) flag = false; // 先手一定不是必败态,因为后手有平局
}
}
mp[st] = flag?-1:2;
// cout <<st <<" " << mp[st] << endl;
return mp[st];
}
int main() {
cin >> n;
int t = dfs(1);
if(t == -1) {
puts("Sheep");
} else if(t == 2) {
puts("平局");
} else
puts("Panda");
return 0;
}
需要打表到>16才能发现正确规律。
- n < 7 平局。
- n >= 7 && n < 16 ,n为奇数 Panda,否则平局。
- n >= 16,n为奇数 Panda,n为偶数 Sheep。
代码
#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,int> pii;
int main() {
int T;
cin >> T;
for(int kas = 1; kas <= T; ++kas) {
printf("Case #%d: ", kas);
int n;
cin >> n;
if(n < 7) {
puts("Draw");
} else if( n >= 7 && n < 16) {
if(n&1) puts("Panda");
else puts("Draw");
} else {
if(n&1) puts("Panda");
else puts("Sheep");
}
}
return 0;
}
1万+



被折叠的 条评论
为什么被折叠?



