【問題描述】
小秋秋想出去玩了。。
小秋秋有許多朋友,有一些小秋秋的朋友相互之間也是朋友。。。
小秋秋覺得自己帶不是朋友的兩個朋友出去玩會出現尷尬。。。(好糾結)
小秋秋想知道自己最多可以帶多少朋友出去玩以及帶人最多的方案數。。
首先最大團等於補圖的最大獨立集
所以將補圖中每個點的出邊用int64記錄
for i := 人數 downto 1 計算從 i 到 n 的最大獨立集
爲什麼要這麼做呢?因爲會有個很好的剪枝。搜索到k時,如果tot + f[i] < ans 就直接退出
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<climits>
#define ot "%d"
#ifdef WIN32
#define otl "%I64d"
#else
#define otl "%lld"
#endif
#define Max(t, a, b) ({t _ = (a), __ = (b); _ > __ ? _ : __;})
#define max(a, b) ({int _ = (a), __ = (b); _ > __ ? _ : __;})
#define Min(t, a, b) ({t _ = (a), __ = (b); _ < __ ? _ : __;})
#define swap(t, a, b) ({t _ = (a); (a) = (b); (b) = _;})
#define maxn 55
using namespace std;
int n, m, s, kind, ans, f[maxn];
long long a[maxn];
void init()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf(ot ot, &n, &m);
int x, y;
a[0] = (1ll << (n + 1ll)) - 2ll;
for (int i = 1; i <= n; ++i) a[i] = a[0];
for (int i = 1; i <= m; ++i)
{
scanf(ot ot, &x, &y);
a[x] &= a[0] ^ (1ll << y), a[y] &= a[0] ^ (1ll << x);
}
}
void up(int k)
{
if (k > ans) ans = k, kind = 1;
else if (k == ans) ++kind;
}
void dfs(int now, int tot, long long v)
{
if (now > n) {up(tot); return;}
if (tot + f[now] < ans) return;
if (!(v & a[now])) dfs(now + 1, tot + 1, (v | (1ll << now)));
dfs(now + 1, tot, v);
}
int main()
{
init();
ans = 0, kind = 0;
for (int i = n; i; --i)
{
dfs((i + 1), 1, (1 << i));
f[i] = ans;
}
printf(ot " " ot, ans, kind);
return 0;
}
跑得非常快,0.3左右即可出解。
2.下棋(chess)
【問題描述】
學習之餘,小秋秋還喜歡進行棋類活動。。。
現在,小秋秋迷上了一個叫tic-tac-toe的遊戲。。(這種詭異的名字?原題如此)。這個遊戲是兩個人輪流在4*4的格子中放棋子,一個人放滿了一行或一列或一個對角線就算贏。
現在,小秋秋用X先手,已經下過許多步了。他想知道自己現在是否有必勝策略,以及最小的字典序走法。
不知道minimax是拿來做什麼的,但感覺很厲害的樣子。
具體做法請看http://blog.csdn.net/a2520123/article/details/8061758吧。膜拜...就不放我的了。