uva11795 Mega Man's Mission

本文介绍了一种使用二进制表示和动态规划解决特定机器人消灭问题的方法。通过枚举所有可能的消灭组合并利用武器获取机制,文章详细阐述了如何计算出消灭所有机器人的可行方案数量。

题意:(终于能打中文了= =)

先给几把武器来消灭机器人(字符串为1是表示这个编号的机器人可消灭), 然后再给出先灭当前的机器人之后获得的武器(即消灭其他机器人的能力),求消灭所有机器人的方案

思路:

用二进制来表示消灭的机器人以及有的可消灭某编号的机器人的武器

首先枚举消灭机器人的所有情况,作为下标,然后数组存储的是这种情况下拥有的武器

(这里产生了很大的困惑,应为消灭机器人明显是有先后关系的,这样处理会不会有逻辑上的错误)

然后枚举所有的情况,每种情况都与每个机器人相与,假如这个机器人可消灭但是未消灭,那么这个机器人消灭的方案就可以加上这个机器人未消灭的方案(即当前方案)

那么上述的困惑可以这样解释:

s[0]是一定符合逻辑的,那么我杀一个人的时候也一定是符合逻辑的,

那么dp[i]在这种逻辑之下得到值,如果dp[i]没有值,那么就是空操作,也就是说,必须是之前已经的到的方案才可,那么如果这个杀人的方案也就是i是不符合逻辑的,那么他是不会有值的,直到他符合逻辑为止,他才会有值

代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn = 65540;
int s[maxn], weapon[maxn];
char robot[18], mega[18];
long long dp[maxn];
int n;
int main() {
	int kase=1, k;
	scanf("%d", &k);
	while(k--) {
		scanf("%d%s", &n, mega);
		memset(dp, 0, sizeof(dp));
		memset(weapon, 0, sizeof(weapon));
		memset(s, 0, sizeof(s));
		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[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] & (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)) && (i&(1<<j))==0) {
					dp[i|(1<<j)] += dp[i];
				}
			}
		}

		printf("Case %d: %lld\n", kase++, dp[(1 << n) - 1]);  
	}  
	return 0;  
}  







评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值