一开始以为抢来的武器只能用一次,结果tle了一发,晕。。。
思路:
看到N的范围就知道可以枚举子集了。
dp[i]表示状态i的结果。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1.0);
int n, m, k;
string p;
vector<string> mat;
vll dp;
ll recur(int s, int w){
if(!s)
return 1;
if(dp[s] >= 0)
return dp[s];
ll res = 0;
for(int i = 0; (1 << i) <= s; i++)
if((s & (1 << i)) && (w & (1 << i))){
int cur = w;
for(int j = 0; j < n; j++)
if(mat[i][j] - '0')
cur |= (1 << j);
res += recur(s ^ (1 << i), cur);
}
return dp[s] = res;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
int times;
cin >> times;
for(int t = 1; t <= times; t++){
cin >> n >> p;
mat.clear();
mat.resize(n);
for(int i = 0; i < n; i++)
cin >> mat[i];
dp.clear();
dp.resize(1 << n, -1);
int w = 0;
for(int i = 0; i < n; i++)
if(p[i] - '0')
w |= (1 << i);
cout << "Case " << t << ": ";
cout << recur((1 << n) - 1, w) << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。