您的位置:首页 > 其它

UVA 11795 Mega Man's Mission(状态压缩DP)

2014-04-20 12:56 459 查看
题意:需要打败N个敌人,初始给出了一个武器,武器能打败一些敌人,打败一个敌人之后就能得到敌人的武器,其武器又可以打败另外的一些敌人,可以携带多把武器.求打败所有敌人的不同顺序数.

思路:注意到N最大只有16,可以用状态压缩来做,把敌人的死亡情况压缩成二进制.

dp[i]表示敌人死亡情况的二进制为i时的方案数,

S[i]表示敌人死亡情况的二进制位i时,拥有的武器的二进制表示.

那么dp[t] += dp[i] 满足t的二进制有一位不同,即敌人死亡情况二进制i时拥有的武器二进制S[i]里有一个敌人还没有被杀死过.

base case: dp[0] = 1

#include <cstdio>
#include <memory.h>
using namespace std;
const int MAX = 65540;

int S[MAX];
long long dp[MAX];
int weapon[18];
char robot[18];
char mega_buster[18];
int main(int argc, char const *argv[]){
int T, caseno = 1;
scanf("%d", &T);
while(T--){
int N;
scanf("%d%s", &N, mega_buster);
memset(S, 0, sizeof(S));
memset(dp, 0, sizeof(dp));
memset(weapon, 0, sizeof(weapon));

for(int i = 0; i < N; ++i){
scanf("%s", robot);
for(int j = 0; j < N; ++j){
if(robot[j] == '1'){
weapon[i] |= (1 << j);
}
}
}

for(int i = 0; i < N; ++i){
if(mega_buster[i] == '1'){
S[0] |= (1 << i);
}
}

for(int i = 0; i < (1 << N); ++i){
S[i] = S[0];
for(int j = 0; j < N; ++j){
if((i & (1 << j))){
S[i] |= weapon[j];
}
}
}

dp[0] = 1;
for(int i = 0; i < (1 << N); ++i){
if(dp[i] == 0)continue;
for(int j = 0; j < N; ++j){
if((S[i] & (1 << j)) != 0 && (i & (1 << j)) == 0){
dp[i | (1 << j)] += dp[i];
}
}
}
printf("Case %d: %lld\n", caseno++, dp[(1 << N) - 1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: