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的更多相关文章

  1. 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 ...

  2. 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 ...

  3. Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】

    题目链接:http://codeforces.com/problemset/problem/453/B 题意: 给你一个长度为n的数列a,让你构造一个长度为n的数列b. 在保证b中任意两数gcd都为1 ...

  4. codeforces 454 D. Little Pony and Harmony Chest(状压dp)

    题目链接:http://codeforces.com/contest/454/problem/D 题意:给定一个序列a, 求一序列b,要求∑|ai−bi|最小.并且b中任意两数的最大公约数为1. 题解 ...

  5. [CF453B]Little Pony and Harmony Chest

    [CF453B]Little Pony and Harmony Chest 题目大意: 给你一个长度为\(n(n\le100)\)的正整数序列\(A(A_i\le30)\),求一个正整数序列\(B\) ...

  6. Codeforces 454D - Little Pony and Harmony Chest

    454D - Little Pony and Harmony Chest 思路: 状压dp,由于1的时候肯定满足题意,而ai最大是30,所以只要大于等于59都可以用1替换,所以答案在1到59之间 然后 ...

  7. CF 435B Little Pony and Harmony Chest

    Little Pony and Harmony Chest 题解: 因为 1 <= ai <= 30 所以  1 <= bi <= 58, 因为 59 和 1 等效, 所以不需 ...

  8. Codeforces 4538 (状态压缩dp)Little Pony and Harmony Chest

    Little Pony and Harmony Chest 经典状态压缩dp #include <cstdio> #include <cstring> #include < ...

  9. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

随机推荐

  1. 005-循环结构(上)-C语言笔记

    005-循环结构(上)-C语言笔记 学习目标 1.[掌握]switch-case结构 2.[理解]case语句穿透 3.[理解]Xcode断点调试 4.[理解]while循环结构初体验 5.[掌握]w ...

  2. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(四)之Operators

    At the lowest level, data in Java is manipulated using operators Using Java Operators An operator ta ...

  3. Simple Chat Application for Python

    一.知识点介绍: asyncore .asynchat模块使用 由于 Python 是一门带 GIL 的语言,所以在 Python 中使用多线程处理IO操作过多的任务并不是很好的选择.同时聊天服务器将 ...

  4. 实例讲解Springboot整合MongoDB进行CRUD操作的两种方式

    1 简介 Springboot是最简单的使用Spring的方式,而MongoDB是最流行的NoSQL数据库.两者在分布式.微服务架构中使用率极高,本文将用实例介绍如何在Springboot中整合Mon ...

  5. Oracle使用fy_recover_data恢复truncate删除的数据

    (一)truncate操作概述 在生产中,truncate是使用的多的命令,在使用不当的情况下,往往会造成表的数据全部丢失,恢复较为困难.对于truncate恢复,常见的有以下几种方法可以进行恢复: ...

  6. 今天探究的CSS属性是box-sizing;

    首先BOX-SIZING属性是CSS3的属性: 语法: box-sizing : content-box || border-box || inherit 取值说明 1.content-box:此值为 ...

  7. 【半译】在ASP.NET Core中创建内部使用作用域服务的Quartz.NET宿主服务

    在我的上一篇文章中,我展示了如何使用ASP.NET Core创建Quartz.NET托管服务并使用它来按计划运行后台任务.不幸的是,由于Quartz.NET API的工作方式,在Quartz作业中使用 ...

  8. CVE-2019-0193 Apache solr velocity模块漏洞

    Solr简单介绍 Solr是建立在Apache Lucene ™之上的一个流行.快速.开放源代码的企业搜索平台. Solr具有高度的可靠性,可伸缩性和容错能力,可提供分布式索引,复制和负载平衡查询,自 ...

  9. Mysql中的一些类型

    列类型--整数类型Tinyint:迷你整形 一个字节=8位 最大能表示的数值是0-255 实际区间 -128~127Smallint:小整形 两个字节 能表示0-65535Mediumint:中整型 ...

  10. MySQL之慢日志记录、分页

    1.慢日志记录 slow_query_log = OFF #是否开启慢日志记录 long_query_time = 2 #时间限制,超过此时间,则记录 slow_query_log_file = C: ...