[ABC354E] Remove Pairs
AT_abc354_e Remove Pairs
题意简述
给定
思路
暴力( 16/30 个点)
首先我们可以先想着暴力的直接搜索。由于
- 没有下一层,这一层是必败状态
- 下一层全部是必胜状态,那么这一层是必败状态
- 下一层有必败状态,这一层是必胜状态
时间复杂度是阶乘级别的。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define ld long double
inline ll read(){
ll res = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
res = res * 10 + c - '0';
c = getchar();
}
return f * res;
}
const int N = 20, M = 2000010;
struct ii{
ll a, b;
}card[N];
bool f[M];
ll n;
bool dfs(ll now){
bool flag = 0;
for(int i = 1; i <= n; i ++){
if(!((now >> (i - 1)) & 1))continue;
ll mid = now - (1 << (i - 1));
for(int j = i + 1; j <= n; j ++){
if(!((mid >> (j - 1)) & 1))continue;
if(!(card[i]. a == card[j]. a || card[i]. b == card[j]. b))continue;
ll midd = mid - (1 << (j - 1));
if(!dfs(midd)){
flag = 1;
}
}
}
return flag;
}
signed main(){
n = read();
for(int i = 1; i <= n; i ++){
card[i]. a = read(), card[i]. b = read();
}
if(dfs((1ll << n) - 1)){
cout << "Takahashi";
}
else{
cout << "Aoki";
}
return 0;
}
正解 #1
我们都把状态用二进制表示出来了,那么我们对于每一个状态只需要搜所以此就可以。所以我么们用一个
代码 #1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define ld long double
inline ll read(){
ll res = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
res = res * 10 + c - '0';
c = getchar();
}
return f * res;
}
const int N = 20, M = 2000010;
struct ii{
ll a, b;
}card[N];
int f[M];
ll n;
bool dfs(ll now){
if(f[now] != -1)return f[now];///////////
bool flag = 0;
for(int i = 1; i <= n; i ++){
if(!((now >> (i - 1)) & 1))continue;
ll mid = now - (1 << (i - 1));
for(int j = i + 1; j <= n; j ++){
if(!((mid >> (j - 1)) & 1))continue;
if(!(card[i]. a == card[j]. a || card[i]. b == card[j]. b))continue;
ll midd = mid - (1 << (j - 1));
if(!dfs(midd)){
flag = 1;
}
}
}
f[now] = flag;///////////
return flag;
}
signed main(){
n = read();
memset(f, -1, sizeof f);
for(int i = 1; i <= n; i ++){
card[i]. a = read(), card[i]. b = read();
}
if(dfs((1ll << n) - 1)){
cout << "Takahashi";
}
else{
cout << "Aoki";
}
return 0;
}
正解 #2
都用到状压了,怎么能不用 DP 呢?
状态设计同上。我们从小到大枚举状态,再枚举物品对,那么我们在转移时(例如要从不选
代码 #2
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define ld long double
inline ll read(){
ll res = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
res = res * 10 + c - '0';
c = getchar();
}
return f * res;
}
const int N = 20, M = 2000010;
struct ii{
ll a, b;
}card[N];
bool f[M];
ll n;
bool check(){
for(ll now = 0; now < (1 << n); now ++){
for(int i = 1; i <= n; i ++){
if(!((now >> (i - 1)) & 1))continue;
ll mid = now - (1 << (i - 1));
for(int j = i + 1; j <= n; j ++){
if(!((mid >> (j - 1)) & 1))continue;
if(!(card[i]. a == card[j]. a || card[i]. b == card[j]. b))continue;
ll midd = mid - (1 << (j - 1));
if(!f[midd])f[now] = 1;
}
}
}
return f[(1 << n) - 1];
}
signed main(){
n = read();
for(int i = 1; i <= n; i ++){
card[i]. a = read(), card[i]. b = read();
}
if(check()){
cout << "Takahashi";
}
else{
cout << "Aoki";
}
return 0;
}