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

81 篇文章 1 订阅

题意:需要打败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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值