uva 11795(状态压缩dp)

题意:有一个机器人要杀死其他n(1 <= n <= 16)个机器人,他自己配备了一个武器,并且给出了这个武器能杀死的敌人,如101表示他能杀死第1和第3个敌人,这样他就能得到第1和第3号敌人的武器,从而杀死更多的敌人,问他杀死所有的敌人的方法数。

题解:因为敌人数最多是16个,很容易想到应该是状态压缩dp,可以用f[S]表示状态S下进制位为1的敌人全被杀死的方案数,那么结果就是f[(1 << n) - 1],如果拿掉了状态S中的杀死第j个人能得到的武器,剩下的人如果能杀死第j个人,就把这个状态的方法数加到f[S]中。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 20;
const int M = (1 << 16) + 100;
int n, w[N], s[M];
char str[N];
long long f[M];

int main() {
    int t, cas = 1;
    scanf("%d", &t);
    while (t--) {
        memset(f, 0, sizeof(f));
        scanf("%d", &n);
        int all = (1 << n) - 1;
        for (int i = 0; i < n + 1; i++) {
            scanf("%s", str);
            w[i] = 0;
            for (int j = 0; j < n; j++)
                if (str[j] == ‘1‘)
                    w[i] |= (1 << j);
        }
        //s[i]表示在状态i下杀死进制位是1的所有能杀死的人
        //f[i]表示在状态i下的能把进制位是1的杀死的方案数
        s[0] = w[0];
        for (int i = 1; i <= all; i++) {
            s[i] = w[0];
            for (int j = 0; j < n; j++)
                if ((i >> j) & 1)
                    s[i] |= w[j + 1];
        }
        f[0] = 1;
        for (int i = 1; i <= all; i++) {
            for (int j = 0; j < n; j++)
                if ((s[i ^ (1 << j)] >> j) & 1)
                    f[i] += f[i ^ (1 << j)];
        }
        printf("Case %d: %lld\n", cas++, f[all]);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-10 16:35:29

uva 11795(状态压缩dp)的相关文章

uva 1252(状态压缩dp)

题意:有n个二进制串,长度都是m且都不相同,问最少询问多少个问题可以把这n个串完全区分开. 题解:1<=m<=11,从这个范围就可以推测是状态压缩,那么dp肯定要有一维表示提问的问题,然后另一位就是根据提出的问题把串分类,一种是符合提出的问题的状态,另一种不符合.这样f[i][j]表示在问了问题i的状态下答案是状态j时还要提出多少个问题才能把所有串区分开. 如果找到在问题i下和答案j相同的串只有1串或没有,说明f[i][j]=0不需要再提问就已经区分开了,否则就要再提问问题,把之前问题i的位上

uva 10817 状态压缩DP

题意: 有S个课程要教, 学校本来有m个教师 给出工资和所教课程编号  (在职教师不能辞退) 来应聘的有n个教师 给出工资和所教课程编号 问保证每个课程都有两个老师可以教的前提下,最少发多少工资 思路: 水题: 总共最多只有8个课程,状态压缩 d[i][s1][s2] 表示当前状态下,有一个老师教的课程是s1,有两个或两个人以上教的课程是s2 转移就是当前教师选或不选,对应的转移到下一个(i+1个)教师的决策即可. code: #include<cstdio> #include<iost

UVA 11825 状态压缩DP+子集思想

很明显的状态压缩思想了.把全集分组,枚举每个集合的子集,看一个子集是否能覆盖所有的点,若能,则f[s]=max(f[s],f[s^s0]+1).即与差集+1比较. 这种枚举集合的思想还是第一次遇到,果然太弱了....~~~~ 其中枚举集合 for(s0=s;s0;s0=(s0-1)&s) #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> usin

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

UVA 11825 - Hackers&amp;#39; Crackdown 状态压缩 dp 枚举子集

UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共同拥有n种服务,每台计算机上都执行着所有服务,对于每台计算机,你能够选择停止一项服务,这个行为会导致与这台计算机和与他相连的其它计算机上的这项服务都停止(原来已经停止的继续保持停止状态). 求最多能使多少个服务瘫痪(即没有不论什么一台计算机在执行这项服务). 分析: 题目说白了.就

uva 11825 Hackers&#39; Crackdown(状态压缩DP)

Hackers' Crackdown Input: Standard Input Output: Standard Output   Miracle Corporations has a number of system services running in a distributed computer system which is a prime target for hackers. The system is basically a set of N computer nodes wi

uva 11825 ,Hacker&#39;s Crackdown 状态压缩 dp

// uva 11825 Hacker's Crackdown // // 题目意思看了很久才看懂,有n台计算机,有n种服务,每台计算机上运行所有 // 的服务,并且其中有的计算机与某些计算机相互邻接,对于每台计算机, // 你可以选择一项服务,停止这项服务,则与它邻接的计算机的该服务也停止了 // 你的目的是让经量多的服务完全瘫痪 // // 换而言之,这个问题就是在n个集合中(p[1]....p[n])分成尽量多的组数,使得每组 // 的并集等于全集(即所有的n台电脑都停止)... // /

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个格子不能相邻,并且取出的数