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][ ...
随机推荐
- Linux Mint(Ubuntu)如何管理开机自动启动项?
Linux Mint自带了一个简洁的开机自启管理应用,使用方法也很简单: 依次点击“Menu”==>“控制中心”==>“个人”==>“启动应用程序”,界面如图所示: 上面打勾的就是系 ...
- 自己实现一个 DFA 串模式识别器
自己实现一个 DFA 串模式识别器 前言 这是我编译原理课程的实验.希望读完这篇文章的人即便不知道 NFA,DFA 和正规表达式是什么,也能够对它们有一个简单的理解,并能自己去实现一个能够识别特定模式 ...
- Redis之ziplist源码分析
一.ziplist简介 从上一篇分析我们知道quicklist的底层存储使用了ziplist(压缩列表),由于压缩列表本身也有不少内容,所以重新开了一篇,在正式源码之前,还是先看下ziplist的特点 ...
- 对于不平凡的我来说,从小我就在想为啥别人就什么都能拥有,而看看自己却什么都没有,对于原来的我就会抱怨爸妈怎么没有别人父母都能给自己想要的,可我从未想过父母的文化只有小学,其实父母内心也有太多的辛酸,所以我不甘愿如此,从此让我在大学里面直接选择一个让我巨大的转折————IT。
对于不平凡的我来说,从小我就在想为啥别人就什么都能拥有,而看看自己却什么都没有,对于原来的我就会抱怨爸妈怎么没有别人父母都能给自己想要的,可我从未想过父母的文化只有小学,其实父母内心也有太多的辛酸,所 ...
- Beta-release 目标
在第二个release开发周期中我们首要先要完成的是对第一个发布版本的优化:(之前团队在跟travis的沟通中,travis也要求我们首先要把现在已有的feature做到一个比较成熟和稳定的版本) 1 ...
- vue单页应用和和多页应用的区别
个人见解如下: 单页面应用(SinglePage Web Application )简称:SPA 多页面应用 (MultiPage Application) 简称:MPA 组成一个外壳和多个页面片段 ...
- PHP xml 外部实体注入漏洞学习
XML与xxe注入基础知识 1.XMl定义 XML由3个部分构成,它们分别是:文档类型定义(Document Type Definition,DTD),即XML的布局语言:可扩展的样式语言(Exten ...
- react: typescript integrate withRouter
define interface: export interface INav { nav: string } export interface IModuleItem { state?: strin ...
- Java集合linkdList
LinkedList特有功能: A:添加功能 public void addFitst(Object e) public void addLast(Object e) B:获取功能 public Ob ...
- pytorch中tensor的属性 类型转换 形状变换 转置 最大值
import torch import numpy as np a = torch.tensor([[[1]]]) #只有一个数据的时候,获取其数值 print(a.item()) #tensor转化 ...