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][ ...
随机推荐
- Java异常处理总结Exception\Error
Java异常处理总结Exception\Error 2012-12-28 08:17:17| 分类: JAVA | 标签:java |举报|字号 订阅 Java异常处理总结 ...
- 2020年iOS进阶面试题总结(一)
准备找工作的你,可以看看,复习复习!! 1.说一下OC的反射机制 在动态运行下我们可以构建任何一个类,然后我们通过这个类知道这个类的所有的属性和方法,并且如果我们创建一个对象,我们也可以通过对象找到这 ...
- python填写金数据
''' 将 main 中的{url}改为真 url 将 setd_data中 {姓名} {纬度} {经度} {地址} 改为确切数据 数据自行参考post 结果判断基于响应中是否包含“谢谢参与”字样 ' ...
- java nio消息半包、粘包解决方案
问题背景 NIO是面向缓冲区进行通信的,不是面向流的.我们都知道,既然是缓冲区,那它一定存在一个固定大小.这样一来通常会遇到两个问题: 消息粘包:当缓冲区足够大,由于网络不稳定种种原因,可能会有多条消 ...
- Linux 命令系列之 seq
简介 seq -- print sequences of numbers seq 命令可以输出各种有规律的数字. 用法 usage: seq [-w] [-f format] [-s string] ...
- Sprint 5 summary: UI 界面更新,Azure端部署和用户反馈分析 12/28/2015
本次sprint主要完成的任务有对手机APP的UI界面的更新,同时对Azure客户端的部署进行了相应的学习和有关的程序设计.同时对于ALPHA release的用户反馈做出相应的分析以确定接下来工作的 ...
- mongo基础
以下如有任何问题,直接到官方操作文档左上角搜索框搜索 安装 On Windows, this path is on the drive from which you start MongoDB. Fo ...
- pytorch中tensor张量的创建
import torch import numpy as np print(torch.tensor([1,2,3])) print(torch.tensor(np.arange(15).reshap ...
- Java面试系列第3篇-HashMap相关面试题
HashMap是非线程安全的,如果想要用线程安全的map,可使用同步的HashTable或通过Collections.synchronizeMap(hashMap)让HashMap变的同步,或者使用并 ...
- 全网最全最细的appium自动化测试环境搭建教程以及appium工作原理
一.前言 对于appium自动化测试环境的搭建我相信90%的自学者都是在痛苦中挣扎,在挣扎中放弃,在放弃后又重新开始,只有10%的人,人品比较好,能够很快并顺利的搭建成功.appium 自动化测试 ...