连锁商店 状态压缩dp(女赛)
题意 :
- 每个点都属于一家公司,每个点都对应一个权值。对于一条路径,属于同一家公司的一些点的贡献只能被算一次。给一张图,路径只能从小往大走,问从1走到每个点路径上分别的最大权值和
思路 :
- n最大为36,说明出现多个点的公司最大为n2\frac{n}{2}2n,不难发现,对于同一条路径,如果这条路径上有些点所属公司只有这个点,那么必然直接选上这个点,对于只出现过一次的商店不需要存入状态
- 出现状态分裂的状况为出现多个点那些公司,这些才存入状态,那么时间复杂度是O(2n2∗n2)O(2^{\frac{n}{2}}*n^{2})O(22n∗n2),如果不优化的话就是O(2n∗n2)O(2^{n}*n^2)O(2n∗n2)会T
- 可以用二进制压缩出现多个点的公司的状态,dp[i][j]dp[i][j]dp[i][j]表示当前在i点,出现多个点的公司状态为j
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <unordered_map>
#define fi first
#define se second
#define pb push_backusing namespace std;typedef long long ll;const int N = 40, M = 1 << 20;int n, m;
int c[N], w[N];
int dp[40][M];
vector<int> edge[N];
unordered_map<int, int> mp;
vector<int> ve;void solve()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; i ++ ){scanf("%d", &c[i]);mp[c[i]] ++ ;}for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);for (auto w : mp)if (w.se > 1)ve.pb(w.fi);for (int i = 1, u, v; i <= m; i ++ ){scanf("%d%d", &u, &v);edge[v].pb(u); // v能由u到达}edge[1].pb(0);for (int i = 1; i <= n; i ++ ){int id = -1; // id为-1说明这个点所属公司只有这家店,否则,id代表这个点所属的公司for (int j = 0; j < (int)ve.size(); j ++ )if (c[i] == ve[j]){id = j;break;}if (id == -1) // 直接加上{for (int j = 0; j < (1 << (int)ve.size()); j ++ )for (auto from : edge[i])dp[i][j] = max(dp[i][j], dp[from][j] + w[c[i]]);}else // 需要判断当前取还是不取{for (int j = 0; j < (1 << (int)ve.size()); j ++ ) // 当前,所有公司是否已经被取过的状态{if (j & (1 << id)) // 当前i这个点所在公司之前已经取过,判断当前已经取过的状态和没有取过然后加上当前这个{for (auto from : edge[i])dp[i][j] = max(dp[i][j], dp[from][j ^ (1 << id)] + w[c[i]]); // 后者是之前不取取当前的}else // 计算不拿的状态{for (auto from : edge[i])dp[i][j] = max(dp[i][j], dp[from][j]);}}}int ans = 0;for (int j = 0; j < (1 << (int)ve.size()); j ++ ) ans = max(ans, dp[i][j]);cout << ans << endl;}
}int main()
{// ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);int _ = 1;
// cin >> _;while (_ -- ){solve();}return 0;
}
连锁商店 状态压缩dp(女赛)相关推荐
- 0x56. 动态规划 - 状态压缩DP(习题详解 × 7)
目录 Problem A. 最短Hamilton路径 ProblemB. 蒙德里安的梦想 Problem C. Corn Fields Problem D. 小国王 Problem E. 炮兵阵地 P ...
- POJ 2411 Mondriaan‘s Dream(最清楚好懂的状压DP讲解)(连通性状态压缩DP)
poj 2411 Mondriaan's Dream(最清晰的状压DP解析) 闫氏DP大法好 我们这里是一列一列地来,因为是一个棋盘性的状态压缩DP,从哪个方向都一样 摆放的小方格总方案数 等价于 横 ...
- BZOJ1688|二进制枚举子集| 状态压缩DP
Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) ...
- hdu1074 状态压缩dp+记录方案
题意: 给你一些作业,每个作业有自己的结束时间和花费时间,如果超过结束时间完成,一天扣一分,问你把n个作业完成最少的扣分,要求输出方案. 思路: 状态压缩dp,记录方案数的地方 ...
- FZU-2218 Simple String Problem(状态压缩DP)
原题地址: 题意: 给你一个串和两个整数n和k,n表示串的长度,k表示串只有前k个小写字母,问你两个不含相同元素的连续子串的长度的最大乘积. 思路: 状态压缩DP最多16位,第i位的状态表示第i位字母 ...
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 91. 最短Hamilton路径:位运算、状态压缩dp、dp
文章目录 题目解答 题目链接 题目解答 分析: 状态压缩dp是用二进制数来表示状态. 数据范围n = 20, 那么状态总量就是2202^{20}220个状态. 可以按照以下思路去思考: 哪些点被用过 ...
- 状态压缩DP AcWing算法提高课 (详解)
基础课的状态压缩点这里 基础课中 蒙德里安的梦想 属于 棋盘式状态压缩dp,最短Hamilton路径 属于 集合状态压缩dp 1064. 小国王(棋盘式/基于连通性) 这种棋盘放置类问题,在没有事先知 ...
- hdu 5067(状态压缩dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5067 解题思路:这道题开始想复杂了,想用bfs去求出最短距离,其实没必要,因为题目中没有阻碍关系,所以 ...
- hdu 5418(状态压缩dp+Floyd)
点击打开链接 解题思路:这道题目和TSP问题很相似,唯一不同的是同一个点可以重复走几次.... 这道题目只有16个顶点,所以很容易想到状态压缩dp,dp[i][j]表示到达顶点i时的状态为j的最小花费 ...
最新文章
- uniapp 中如何使用echart_uniapp中如何引用echarts
- 输出200-299之间的所有素数
- boost::program_options模块一个配置ini文件被解析程序选项库,它包括许多不同的值类型的测试程序
- 自动ping博客服务程序
- C语言 | 赋值与运算符
- 1143 多少个Fibonacci数
- opencv-api findHomography
- flash as3笔记1
- Java中的>>,>>>
- 计算机组成原理与体系结构知识概括
- visio画图-去掉visio中多余的连接点
- 提取整数的各个位数 (Separating the Digits in an Integer)
- 渠道分销管理系统解决方案
- 解剖点击量过亿的软文牛人是怎样炼成的?
- vivo X70系列搭载自研V1芯片9月9日发布
- 004/160 CrackMe ajj CKme
- C++stack与queue模拟实现
- ACP学习笔记(云计算)附题
- 路缘石成型机应对公路项目施工的技术层面
- windows桌面便笺使用小技巧Win10便利贴不见了在哪里调出来Win10便签怎么用