题意:(终于能打中文了= =)
先给几把武器来消灭机器人(字符串为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;
}
本文介绍了一种使用二进制表示和动态规划解决特定机器人消灭问题的方法。通过枚举所有可能的消灭组合并利用武器获取机制,文章详细阐述了如何计算出消灭所有机器人的可行方案数量。
328

被折叠的 条评论
为什么被折叠?



