M - Little Pony and Harmony Chest 状压dp
M - Little Pony and Harmony Chest
怎么感觉自己越来越傻了,都知道状态的定义了还没有推出转移方程。
首先这个a的范围是0~30 这里可以推出 b数组的范围 0~60
原因很简单,因为这个要求abs(b-a)) 尽量小,所以如果b>=60 那还不如用1 ,因为1 的数量是没有限制的,
当 b>60 abs(b-a)>30 所以相比 b>60 b==1 更优。
然后我们对质数进行状压,为什么要对质数进行状压呢,因为质数两两互质,而且每一个数都是由若干个质数组成。
所以我们可以用质数来对状态进行筛选。
因为b的范围是从1到58(如果要选59,则也可以选1),所以我们要打个表,来表示他是由哪些素数组成的。
为什么要这样呢,因为这样可以就可以快速判断出之前的状态是不是和这个有冲突(就是有没有相同的质数)
知道这些就差不多了,这个题目利用状压位运算来判断一个两两之间有没有公约数,方法很巧妙。
具体:
dp[i][s] 表示到第 i 个位置,之前的状态为 s 的最小代价,
初始化 dp[0][0]=0,其他都是不合理的状态,所以初始化为inf
首先枚举位置,其次枚举状态,然后在枚举这个位置所有可能的数。
路径的输出就是记录这个状态的放的数,和这个状态之前的状态,一个是记录状态一个是记录数。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + ;
typedef long long ll;
ll dp[][<<];
int is[][<<];
int pre[][<<];
int p[maxn], isp[maxn], m;
void init()
{
memset(p, , sizeof(p));
for (int i = ; i <= ; i++) p[i] = ;
for(int i=;i*i<=;i++)
{
if(p[i])
{
for(int j=i*i;j<=;j+=i)
{
p[j] = ;
}
}
}
m = ;
for(int i=;i<=;i++) if (p[i]) isp[++m] = i;
}
int sta[], a[];
vector<int>e;
int main()
{
int n; init();
scanf("%d", &n);
for (int i = ; i <= n; i++) scanf("%d", &a[i]);
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
if (i%isp[j] == ) sta[i] |= ( << (j - ));//sta 数组表示选i这个数的限制条件,这个要好好理解。
}
}
memset(pre, -, sizeof(pre));
memset(dp, inf64, sizeof(dp));
dp[][] = ;//这个dp定义的是到第i个位置,数的状态为s的代价,
//如果dp == inf 说明是不合理的状态,因为如果是在0这个位置,所以当没有数的状态就是合理的而且代价==0
for(int i=;i<n;i++)//这个从0 开始是因为每次第i个更新第i+1个
{
for(int j=;j<(<<);j++)
{
if (dp[i][j] == inf64) continue;
for(int k=;k<=;k++)
{
if (sta[k] & j) continue;
int tmp = sta[k] | j;
if (dp[i + ][tmp] > dp[i][j] + abs(a[i+] - k))
{
dp[i + ][tmp] = dp[i][j] + abs(a[i+] - k);
is[i + ][tmp] = k;
pre[i + ][tmp] = j;
}
}
}
}
int ans=inf, id=;
for(int i=;i<(<<);i++)
{
if(dp[n][i]<ans)
{
ans = dp[n][i];
id = i;
}
}
for(int i=n;i>=;i--)
{
e.push_back(is[i][id]);
id = pre[i][id];
}
for (int i = e.size() - ; i >= ; i--) printf("%d ", e[i]);
printf("\n");
return ;
}
状压dp
这个题目我现在做感觉不是很简单,之前已经写过一次了,今天又写了一次还是感觉有点迷糊。
明确dp的定义dp[s][i]表示状态为s 上一个节点是i的最小代价。
路径的输出就是记录这一个点这个状态选择的值,再记录上一个点的状态。
根据这个dp定义的状态可以知道要枚举状态和点,先枚举点再枚举每一个点可能的状态,
最后枚举这个点的所有可能性。
先枚举状态不是很好写。
M - Little Pony and Harmony Chest 状压dp的更多相关文章
- Codeforces Round #259 (Div. 2) D. Little Pony and Harmony Chest 状压DP
D. Little Pony and Harmony Chest Princess Twilight went to Celestia and Luna's old castle to resea ...
- CF453B Little Pony and Harmony Chest (状压DP)
CF453B CF454D Codeforces Round #259 (Div. 2) D Codeforces Round #259 (Div. 1) B D. Little Pony and H ...
- Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】
题目链接:http://codeforces.com/problemset/problem/453/B 题意: 给你一个长度为n的数列a,让你构造一个长度为n的数列b. 在保证b中任意两数gcd都为1 ...
- codeforces 454 D. Little Pony and Harmony Chest(状压dp)
题目链接:http://codeforces.com/contest/454/problem/D 题意:给定一个序列a, 求一序列b,要求∑|ai−bi|最小.并且b中任意两数的最大公约数为1. 题解 ...
- [CF453B]Little Pony and Harmony Chest
[CF453B]Little Pony and Harmony Chest 题目大意: 给你一个长度为\(n(n\le100)\)的正整数序列\(A(A_i\le30)\),求一个正整数序列\(B\) ...
- Codeforces 454D - Little Pony and Harmony Chest
454D - Little Pony and Harmony Chest 思路: 状压dp,由于1的时候肯定满足题意,而ai最大是30,所以只要大于等于59都可以用1替换,所以答案在1到59之间 然后 ...
- CF 435B Little Pony and Harmony Chest
Little Pony and Harmony Chest 题解: 因为 1 <= ai <= 30 所以 1 <= bi <= 58, 因为 59 和 1 等效, 所以不需 ...
- Codeforces 4538 (状态压缩dp)Little Pony and Harmony Chest
Little Pony and Harmony Chest 经典状态压缩dp #include <cstdio> #include <cstring> #include < ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
随机推荐
- web.xml配置参数context-param和init-param的区别
web.xml配置参数context-param和init-param的区别 (2009-04-13 10:29:01) 转载▼ 标签: 杂谈 分类: JavaEE web.xml里面可以定义两种参数 ...
- 最长公共子窜和最长公共子序列(LCS)
他们都是用dp做;复杂度都是O(N方) 有一个大佬的博客写的很详细,是关于最长公共子序列的:https://blog.csdn.net/hrn1216/article/details/51534607 ...
- Pytorch自定义创建BP神经网络
class BPNet(nn.Module): def __init__(self, in_dim, n_hidden_1, n_hidden_2,\ n_hidden_3, n_hidden_4, ...
- 通过String的不变性案例分析Java变量的可变性
阅读本文之前,请先看以下几个问题: 1.String变量是什么不变?final修饰变量时的不变性指的又是什么不变,是引用?还是内存地址?还是值? 2.java对象进行重赋值或者改变属性时在内存中是如何 ...
- Docker-Bridge Network 03 自定义网络
本节介绍自定义bridge network的自定义网络. 1.前言2.创建自定义网络2.1 创建网络2.2 指定网段创建网络3.创建容器3.1 指定网络创建容器3.2 指定IP创建容器4.通信4.1 ...
- Crossing River POJ过河问题
A group of N people wishes to go across a river with only one boat, which can at most carry two pers ...
- 详解 final 和 static
在我们上一篇博文中提到了 fianl 这个关键字,对于这个关键字,本人在初学时也耗费了极大地心血,甚至和师兄进行了激烈的讨论,并且,在我们讨论.尝试 以及 翻阅各种资料,最终得出了合适.易懂的解释. ...
- 简谈” Top K“
Top K 快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题. 题见215. Kth Largest Element in an Array (Medium) ...
- php下载各种编辑器输出的内容到word中展示
<?php/** * Created by PhpStorm. * User: 工作 * Date: 2018/1/11 * Time: 12:02 */ //连接数据库$dsn = " ...
- DEDE中自定义表单HTML 怎么写
用DEDE嵌套网站时,有时我们需要添加自定义字段,而自定义字段的HTML样式如何设置呢? 功能地图(核心/频道模型/内容模型管理/)——普通文章的修改——字段管理——你的自定义字段的修改——最下面自定 ...