题目大意:
有
n(n≤18)
个包,并且一个包可能容纳多个包,有以下一种操作:
选出一个没有被其他包容纳的包
a
,将
分析:
数据这么小,当然暴力就可以过了。
不过貌似有一个很神奇的方法答案就是
n+(n>1)
。
AC code:
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define pb push_back
#define ONLINE_JUDGE
using namespace std;
const int MAXN = 20;
int n;
struct Sta
{
vector<int> a[MAXN];
friend bool operator == (const Sta &x, const Sta &y)
{
for(int i = 1; i <= n; ++i)
{
if(x.a[i].size() != y.a[i].size()) return false;
for(int j = 0, sz = x.a[i].size(); j < sz; ++j)
if(x.a[i][j] != y.a[i][j]) return false;
}
return true;
}
}s;
vector<Sta> ans;
queue<Sta> q;
bool vis[MAXN];
bool ins[MAXN];
bool out[MAXN];
bool check(const Sta &x)
{
for(int i = 0, sz = ans.size(); i < sz; ++i)
if(x == ans[i]) return false;
ans.pb(x);
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu238.in", "r", stdin);
freopen("sgu238.out", "w", stdout);
#endif
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
{
int c, x;
scanf("%d", &c);
for(int j = 1; j <= c; ++j)
{
scanf("%d", &x);
s.a[i].pb(x);
}
sort(s.a[i].begin(), s.a[i].end());
}
ans.pb(s);
q.push(s);
while(!q.empty())
{
Sta now = q.front(), to;q.pop();
memset(ins, false, sizeof(ins));
memset(out, false, sizeof(out));
for(int i = 1; i <= n; ++i)
for(int j = 0, sz = now.a[i].size(); j < sz; ++j)
ins[now.a[i][j]] = true;
for(int i = 1; i <= n; ++i)
out[i] = ins[i]^1;
for(int i = 1; i <= n; ++i)
if(!ins[i])
{
to = now;
memset(vis, false, sizeof(vis));
for(int j = 0, sz = to.a[i].size(); j < sz; ++j)
vis[to.a[i][j]] = true;
to.a[i].clear();
for(int j = 1; j <= n; ++j)
if(i != j && !vis[j] && out[j])
to.a[i].pb(j);
if(check(to))
q.push(to);
}
}
printf("%d\n", ans.size());
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}