本文出自 http://blog.csdn.net/shuangde800
題目傳送門
題意:
你最初只有一個武器,你需要按照一定的順序消滅n個機器人(n<=16)。每消滅一個機器人將會得到他的武器。
每個武器只能殺死特定的機器人。
問可以消滅所有機器人的順序方案總數。
思路:
看到了n的規模這麼小,就知道可以用狀態壓縮解決了。
f[s]表示狀態為{s}時的方案總數.
我們設{s-1}是s狀態把一個二進位位是1的變為0的所有情況,相當於集合中少了某個機器人的所有情況
那麼f[s] = sum{ 所有的{s-1}, 消滅了{s-1}個機器人時獲得的武器能夠殺掉少了的這個機器人}
初始化f[0] = 1, 表示一個機器人都不殺的方案有1個
代碼:
/**========================================== * This is a solution for ACM/ICPC problem * * @author: shuangde * @blog: blog.csdn.net/shuangde800 * @email: zengshuangde@gmail.com *===========================================*/#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<cmath>#include<cstring>using namespace std;typedef long long int64;const int INF = 0x3f3f3f3f;const double PI = acos(-1.0);const int MAXN = 10010;int n, maxState;int p[20];char str[20];int kill[(1<<16)+10];int64 f[(1<<16)+10];int main(){ int T; int cas = 1; scanf("%d", &T); while(T--){ scanf("%d", &n); for(int i=0; i<=n; ++i){ scanf("%s", str); p[i] = 0; for(int j=0; str[j]; ++j) if(str[j] == '1') p[i] |= (1<<j); } maxState = (1<<n)-1; kill[0] = p[0]; for(int s=1; s<=maxState; ++s){ kill[s] = p[0]; for(int i=0; i<n; ++i) if((s>>i) & 1) kill[s] |= p[i+1]; } memset(f, 0, sizeof(f)); f[0] = 1; for(int s=1; s<=maxState; ++s){ f[s] = 0; for(int i=0; i<n; ++i)if( (kill[s^(1<<i)]>>i) & 1){ f[s] += f[s^(1<<i)]; } } printf("Case %d: %lld\n", cas++, f[maxState]); } return 0;}