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

Mega Man‘s Mission

Mega Man is off to save theworld again. His objective is to kill the Robots created by Dr.Wily whose motive is
to conquer the world. In each mission, he willtry to destroy a particular Robot. Initially, Mega Man is equippedwith a weapon, called the “Mega Buster”which canbe used to destroy theRobots.  Unfortunately, it mayhappen that his weapon is not
capable of taking down every Robot.However, to his fortune, he is capable of using the weapons fromRobots which he has completelydestroyed and these weapons maybe able to takedown Robots which he otherwise cannot with his own weapon. Notethat,
each of these enemy Robots carryexactly  one weapon themselvesfor fighting Mega Man.  He isable to take down the Robots in any order as long as he has atleast one weapon capable of destroying the Robot at a particularmission. In this problem,
given the information about the Robotsand their weapons, you will have to determine the number of waysMega Man can complete his objective of destroying all theRobots.

Input

Input starts with aninteger T(T50), thenumber of test cases.

Each test case starts with aninteger N(1N16).Here N denotes
thenumber of Robots to be destroyed (each Robot is numbered from 1to N). This line is followedby N+1 lines,eachcontaining N characters.Each
character will eitherbe ‘1’ or ‘0’.These lines representa (N+1)*N matrix.The rows are numbered from 0to N while
thecolumns are numbered from 1 to N.Row 0 represents the information about the “MegaBuster”.The jth characterof Row 0 willbe ‘1’ ifthe “Mega
Buster” can destroythe jth Robot.For theremaining N rows,the jth characterof ith rowwill
be ‘1’ if the weaponof ith Robotcan destroythe jth Robot.Note that, a Robot’s weapon could be
used to destroy the Robotitself, but this will have no impact as the Robot must be destroyedanyway for its weapon to be acquired.

Output

For each case of input, there will be one lineof output. It will first contain the case number followed by thenumber of ways Mega
Man can complete his objective. Look at thesample output for exact format.

Sample Input

3

1

1

1

2

11

01

10

3

110

011

100

000

SampleOutput

Case 1: 1

Case 2: 2

Case 3: 3

题意: 洛克人最初只有一种武器 “Mega Buster”(这种武器可以消灭特定的一些机器人),你需要按照一定的顺序消灭 n 个其他机器人。每消灭一个机器人你将会得到他的武器(也可能没有得到武器),而这些武器可以消灭特定的机器人。你的任务是计算出消灭所有机器人的顺序总数。注意:一个机器人的武器可能可以消灭自己,但这对最终答案没有影响,因为必须先消灭这个机器人才能够得到他的武器。

思路:n 的范围为 [1,16],可以用状态压缩DP来做,用二进制保存状态。时间复杂度为 O(n*2^n) 。首先用 weapon 数组保存杀死这个机器人能得到的武器,用二进制表示,第i位为 1 表示可以杀死第 i 个机器人,为 0 则不可以。其中 weapon[0] 表示原始拥有的武器 (也就是 “Mega Buster” )。用集合 st 来表示杀了的机器人,二进制的1即为杀死了了,0即为没杀死,在该状态下所拥有的武器(所有状态下的初始武器都是
weapon[0] ),用 attack 数组保存所有状态。用 dp[st] 表示在状态为 st 时所有的顺序方案总数。 那么状态转移怎么写呢,

首先,对于每一种状态,我们预处理一下这个状态下可以干掉哪些机器人,这样才能转移,然后对于一个状态 st 来说,要干掉第 i 个机器人,则要从没干掉 i 的状态里面转移,即 s^(1<<i)。

则 dp[s] = sum(dp[s^(1<<i)]) ,条件为 s&(1<<i)   而且 attack[s^(1<<i)] 可以干掉 i。

把 st 里面的所有 1 枚举一次,再加起来即可。

当所有机器人都不杀死的方案总数为 1 , 即 dp[0] = 1 .

<span style="font-size:18px;">#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;

#define ll long long
const double PI = acos(-1.0);
const double e = 2.718281828459;
const double eps = 1e-8;
const int MAXN = (1<<16)+10;
int weapon[MAXN]; // 保存每个机器人可以杀死的机器人
int attack[MAXN]; // 保存每个状态可以杀死的机器人
ll dp[MAXN];  // 2 的 16 次方会爆 int。 // 用来统计每种状态的顺序方案种数
char s[20];

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int Case, n;
    int num = 1;
    cin>>Case;
    while(Case--)
    {
        cin>>n;
        for(int i = 0; i <= n; i++)
        {
            scanf("%s", s);
            weapon[i] = 0;
            for(int j = 0; j < n; j++)
            {
                if(s[j] == '1')
                    weapon[i] |= 1<<j;
            }
            //cout<<i<<" "<<weapon[i]<<endl;
        }
        int total = (1<<n)-1;
        for(int st = 0; st <= total; st++)
        {
            attack[st] = weapon[0];
            for(int i = 1; i <= n; i++)
            {
                int j = i-1;
                if(st&(1<<j))
                {   //如果该状态可以杀死 i,那么该状态也可以杀死i所能干掉的
                    attack[st] |= weapon[i];
                }
            }
            //printf("%d %d\n", st, attack[st]);
        }
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        for(int st = 1; st <= total; st++)
        {
            for(int i = 0; i < n; i++)
            {
                if(st&(1<<i))  // 如果 st 的这种状态能够杀死 i
                {              // 那么 st 由不能杀死 i 的状态转移过来, 即st^(1<<i)
                    if(attack[st^(1<<i)]&(1<<i))
                    {          // 并且要求 st^(1<<i) 这种状态要能够杀死 i
                        dp[st] += dp[st^(1<<i)];
                    }
                }
            }
            //printf("%d %d\n", st, dp[st]);
        }
        printf("Case %d: %lld\n", num++, dp[total]);
    }
    return 0;
}

</span>

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

时间: 2024-10-18 02:27:11

UVa11795 Mega Man's Mission(状态压缩DP)的相关文章

zoj2297Survival (状态压缩DP)

Survival Time Limit: 5 Seconds Memory Limit: 32768 KB The King of Fighter 97 (KOF97) is an electronic game of wrestling type. Once it was fashionable among youths. The game is amused. However, playing by oneself is not as excited as with friends. Get

hdu4758AC自动机+状态压缩DP

http://acm.hdu.edu.cn/showproblem.php?pid=4758 Problem Description On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special l

uva 11795 Mega Man&#39;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.这个很好理解,因为杀死 //

UVA11795 Mega Man&#39;s Mission

状压dp #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<vector> #include<queue> #define MAXN 20 #define ll long long using namespace std; int n; vector<int> G[MAXN]; ll f[1<<MA

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

HDU1565(状态压缩dp)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8170    Accepted Submission(s): 3095 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数

HDU 3001【状态压缩DP】

题意: 给n个点m条无向边. 要求每个点最多走两次,要访问所有的点给出要求路线中边的权值总和最小. 思路: 三进制状态压缩DP,0代表走了0次,1,2类推. 第一次弄三进制状态压缩DP,感觉重点是对数据的预处理,利用数组分解各个位数,从而达到类似二进制的目的. 然后就是状态的表示,dp[s][i]表示状态s时到达i的最优值. 状态转移也一目了然,不废话. #include<stdio.h> #include<string.h> #include<algorithm> u

Victor and World(spfa+状态压缩dp)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)Total Submission(s): 958    Accepted Submission(s): 431 Problem Description After trying hard fo

poj 3311 Hie with the Pie(状态压缩dp)

Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more (up to 10) orders to be