uva 11795 Mega Man's Mission 状压dp

// uva 11795 Mega Man's Mission 状压dp

// 设r[i]表示第i个机器人所拥有的武器的数目
// r[0]表示初始时洛克人所拥有的武器数
// w[s]表示杀死集合s中的机器人后所得的武器数
// d[s]表示能杀死集合s中的机器人的顺序总数
// d[s] = sigma(d[s-{i}])	其中i是集合s中的机器人
// 还有一点就是w[S-{i}]的武器可以杀死i。

// 注意:
// 1)初始的时候d[0]=1,其他均为0.这个很好理解,因为杀死
// 0个机器人的办法就只有1种,其他均不确定能不能完全杀死。

// 感悟:
// 整体上,想到了状压dp.开始的时候我想到的是单独将初始时的
// 武器拿出来,然后处理r[i],处理完w[i],就可以直接进行状压
// 枚举了,结果在初始的武器这个处理上卡住了,完全不知道怎么写
// 后来看了前辈的思路,顿时恍然大悟!可以直接将初始的状态
// 加入到所有的w中S集合中0表示没有杀死任何机器人,不就是初始的
// 武器吗w[0],之后的过程就是水到渠成。
// 这一题中我学到了,有一个初始的状态的时候,不要慌,它可能正好
// 对应于最后所要的集合中的一个特殊的状态,可能是0,也可能全1!

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define ceil(a,b) (((a)+(b)-1)/(b))
#define endl '\n'
#define gcd __gcd
#define highBit(x) (1ULL<<(63-__builtin_clzll(x)))
#define popCount __builtin_popcountll
typedef long long ll;
using namespace std;
const int MOD = 1000000007;
const long double PI = acos(-1.L);

long long d[1<<17];
int r[19];
int w[1<<17];
int n;

void dp(){
	memset(d,0,sizeof(d));
	d[0]=1;
	for (int S=1;S<(1<<n);S++){
		d[S] = 0;
		for(int i=0;i<n;i++){
		// 第一个条件是:i在S中
		// 第二个条件是:在S-{i}(即当前没有杀死i的集合)所获得的武器可以杀死i
			if((S & (1 << i)) && (w[S^(1<<i)] & (1<<i)))
				d[S] += d[S^(1<<i)];
		}
	}
	cout << d[(1<<n)-1] << endl;
}

void init(){
	scanf("%d",&n);
	char s[20];
	for (int i=0;i<=n;i++){
		r[i] = 0;
		scanf("%s",s);
		for (int j=0;s[j];j++){
			if (s[j]=='1')
				r[i] |= 1<< j;
		}
	}
	w[0] = r[0];
	for (int i=1;i<(1<<n);i++){
		w[i] = r[0];//每个w[s]都要加上初始的武器
		for (int j=0;j<n;j++)
			if (i & (1<<j)){
				w[i] |= r[j+1];//这里j+1表示第i个机器人的武器i是从1开始
			}
	}

	dp();
}

int main() {
	int t;
	//freopen("1.txt","r",stdin);
	scanf("%d",&t);
	int kase = 0;
	while(t--){
		printf("Case %d: ",++kase);
		init();
	}
	return 0;
}

uva 11795 Mega Man's Mission 状压dp

时间: 2024-08-25 05:52:27

uva 11795 Mega Man's Mission 状压dp的相关文章

状压DP UVA 11795 Mega Man&#39;s Mission

题目传送门 1 /* 2 题意:洛克人有武器可以消灭机器人,还可以从被摧毁的机器人手里得到武器,问消灭全部机器人的顺序总数 3 状态压缩DP:看到数据只有16,就应该想到状压(并没有).因为是照解题报告写的,代码里加点注释,省的以后忘记了 4 */ 5 /************************************************ 6 * Author :Running_Time 7 * Created Time :2015-8-8 10:41:28 8 * File Nam

UVA - 11795 Mega Man&#39;s Mission

Mega Man is off to save the world again. His objective is to kill the Robots created by Dr. Wily whose motive is to conquer the world. In each mission, he will try to destroy a particular Robot. Initially, Mega Man is equipped with a weapon, called t

【UVa】Headmaster&#39;s Headache(状压dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758 晕....状压没考虑循环方向然后错了好久.. 这点要注意...(其实就是01背包变成了完全背包QAQ 我们将课程拆成两个点,然后状压 那么答案就是(1<<(s<<1))-1 转移就不说了,,,,,太简单.. #include <cstdio> #in

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje

uva 11825 Hackers&amp;#39; Crackdown (状压dp,子集枚举)

题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有同样的n种服务),对每台计算机,你能够选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让很多其它的服务瘫痪(没有计算机有该项服务). 思路:(见大白70页,我的方程与大白不同) 把n个集合P1.P2.Pn分成尽量多的组,使得每组中全部集合的并集等于全集,这里的集合Pi是计算机i及其相邻计算机的集合,用cover[i]表示若干Pi的集合S中全部集合的并集,dp[s]表示子集s最多能够分成多少组,则 假设co

UVA 10944 Nuts for nuts 经典状压DP

https://vjudge.net/problem/UVA-10944 //题意:给出n*m地图,起点为L,每次可以向8个方向移动,地图中有若干个果实,求搜集所有果实后再回到起点的最短路径//n,m<=20,果实个数<=15 则容易用二进制记录当前拿到的果实//设dp[i][state]为当前s在果实i&&拿到的果实状态为state//当2^(i-1) & j==0时,dp[i][j+2^(i-1)]=min(dp[i][j+2^(i-1)],dp[k][j]+dis

uva 10944 Nuts for nuts..(状压dp)

题意:一幅地图中给出松鼠起点,各坚果的信息,求松鼠收集所有坚果并返回起点的最小步数: 思路: 用二进制数表示坚果的收集状态,0表示未收集,1已收集:mm[i][j]表示节点i和j的相对距离:f[i][j]表示在收集状态为j是收集i的最小步数: 显然,收集每颗坚果的最小步数为f[i][2的(i-1)次方]=mm[0][i]; 递增枚举状态值i,状态i中最后被收集的坚果j,枚举i外的坚果k. f[k][i+1<<(k-1)]=min( f[k][i+1<<(k-1)],f[j][i]+

UVa 132 Another Chocolate Maniac(状压DP)

132. Another Chocolate Maniac time limit per test: 0.25 sec. memory limit per test: 4096 KB Bob really LOVES chocolate. He thinks he never gets enough. Imagine his joy when his parents told him that they would buy him many rectangular chocolate piece

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in