UVa 11759 洛克人的难题 状压dp

news/2024/10/17 20:35:44/

题意:

你最初只有一个武器,你需要按照一定的顺序消灭n个机器人(n<=16)。每消灭一个机器人将会得到他的武器。每个武器只能杀死特定的机器人。问可以消灭所有机器人的顺序方案总数。

分析:
基础的集合dp,我是用f[s][num]表示已经得到武器状态s,已经杀了num个机器人后可以得到的方案总数,然后dfs一下就好,比较简单。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 17;
int vis[N], n, a[N];
long long fac[N], f[1 << N][N];
bool flag[1 << N][N];
int ALL; //(1<<n)-1
/*
f[s][num]表示已经得到武器s,已经杀了num个机器人后可以得到的顺序总数
那么如果s==ALL,就说明已经得到所有武器,那么剩下的n-num个人就可以随便杀了(方案数是n-num的全排列)
所以dfs一下就好
*/
ll dfs (int st, int num) {if (st != ALL && num >= n) return 0;if (flag[st][num]) return f[st][num];flag[st][num] = 1;ll& ans = f[st][num];if (st == ALL) {ans = fac[n - num];return ans;}for (int i = 0; i < n; i++) {if (!vis[i] && (st & (1 << i) ) ) {vis[i] = 1;ans += dfs (st | a[i], num + 1);vis[i] = 0; //回溯,可以先不杀这个,先杀其它的}}return ans;
}
int main() {//freopen("f.txt","r",stdin);int T;fac[0] = 1;for (int i = 1; i <= 16; i++) fac[i] = fac[i - 1] * i; //fac[i]保存i的全排列scanf ("%d", &T);for (int cas = 1; cas <= T; cas++) {scanf ("%d", &n );memset (vis, 0, sizeof (vis) );memset (flag, 0, sizeof (flag) );memset (f, 0, sizeof (f) );int st = 0, x;for (int j = 0; j < n; j++) {scanf ("%1d", &x);if (x) st |= (1 << j);}for (int i = 0; i < n; i++) {a[i] = 0;for (int j = 0; j < n; j++) {scanf ("%1d", &x);if (x) a[i] |= (1 << j);}}ALL = (1 << n) - 1;printf ("Case %d: %lld\n", cas, dfs (st, 0) );}return 0;
}

看了别人的想法写的,感觉不错~~

#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 17;
int  n, a[N];
long long f[1 << N], dp[1 << N];
int ALL;
/*
f[s]表示得到状态是s的武器后,可以转移到的状态(也就是还可以杀哪个机器人)
dp[s]表示得到状态s的总方案数
*/
int main() {//freopen("f.txt","r",stdin);int T;scanf ("%d", &T);for (int cas = 1; cas <= T; cas++) {scanf ("%d", &n );memset (f, 0, sizeof (f) );int st = 0, x;for (int j = 0; j < n; j++) {scanf ("%1d", &x);if (x) st |= (1 << j);}for (int i = 0; i < n; i++) {a[i] = 0;for (int j = 0; j < n; j++) {scanf ("%1d", &x);if (x) a[i] |= (1 << j);}}ALL = (1 << n) - 1;for(int s = 0; s <= ALL; s++) {f[s] = st;for(int i = 0; i < n; i++)if(s & (1 << i))f[s] |= a[i]; //统计s状态可以转移到f[s]状态}dp[0] = 1;for(int s = 1; s <= ALL; s++) {dp[s] = 0;for(int i = 0; i < n; i++)if((s & (1 << i)) && (f[s ^ (1 << i)] & (1 << i)))//[s ^ (1 << i)状态通过杀掉第i个机器人可以得到s这个状态dp[s] += dp[s ^ (1 << i)];                    //那么判断是否可以杀掉i的前提就是f[s ^ (1 << i)]有(1 << i)//这个武器}printf ("Case %d: %lld\n", cas, dp[ALL]);}return 0;
}
/*
Input
3
1
1
1
2
11
01
10
3
110
011
100
000
Output
Case 1: 1
Case 2: 2
Case 3: 3*/

http://www.ppmy.cn/news/573025.html

相关文章

洛克人4java7723_最新7723游戏版榜单下载_九游

[详情] Building & crafting and Exploration for age girls! Crafting game for age girls and boys. Girls craft! Exploration of the sandbox blocky world! City builder game! Sim house design craft ! Create your own girls world! Design your dream house, girl…

UVA e 11795 洛克人的难题

题目大意 洛克人有一个武器&#xff0c;它需要按照一定的顺序消灭n个其他的机器人&#xff0c;每消灭一个机器人将会得到他的武器&#xff0c;而且某些机器人只能用特定的武器才能将其消灭。统计出可以消灭所有机器人的顺序总数. 分析 由于题目中给定的n值很小可以采用状压Dp&a…

洛克人java下载_JAVA 1.7并发之LinkedTransferQueue原理理解

昨天刚看完BlockingQueue觉得好高级啊&#xff0c;今天扫到1.7就发现了升级版。。。。 就是作者的论文啦&#xff0c;纯英文。。。比较难啃&#xff0c;但是我觉得逻辑上比看代码容易理解&#xff0c;其实代码什么u啊h啊看得很混 LinkedTransferQueue 起源&#xff1a; 我觉得是…

洛克人html5,《洛克人Zero/Zx合集》:跳票冷饭,与预期有差但依旧很香

前言 洛克人系列&#xff0c;卡普空旗下经典IP之一&#xff0c;一直都是以高难度著称&#xff0c;相信很多90后玩家的童年都有游玩洛克人的经历。从18年发布的洛克人11&#xff0c;整个系列发展有30余年&#xff0c;洛克人元组系列、X系列的合集早已上线Steam&#xff0c;Zero/…

Python多任务执行方式

一、多任务的执行方式 并发&#xff1a;在一段时间内交替去执行任务&#xff08;单核CPU&#xff09;并行&#xff1a;CPU核数大于任务数 二、进程&#xff08;实现多任务&#xff09;——操作系统调度 进程是操作系统进行资源分配的基本单元一个程序至少有一个进程&#xf…

网关全局过滤器:Java中的强大工具

文章目录 网关过滤器简介网关过滤器的作用过滤器的生命周期实际应用示例权限过滤器解析 总结 网关过滤器简介 网关过滤器是一个位于应用程序和底层服务之间的组件&#xff0c;它截取进出网络请求&#xff0c;并提供对请求和响应进行处理的机制。它可以在请求到达目标服务之前或…

10种常用排序算法

10种常用排序算法 0——序言 以下是常用的排序算法及其对应的时间复杂度&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a; 最好情况时间复杂度&#xff1a;O(n)平均情况时间复杂度&#xff1a;O(n^2)最坏情况时间复杂度&#xff1a;O(n^2) 选择排序&a…

c++11中的多线程std::thread

c11中的多线程std::thread 在c11中提供了新的多线程的创建方式std::thread, 丰富了对于多线程的使用。 std::thread类的构造函数的格式如下所示&#xff1a; thread() noexcept; //default constructor 其中noexcept表示函数不会抛出异常&#xff0c;如果抛出异常程序…