状压DP的总结
状压dp的标志
①数据小 ②通过题目所给出的条件以后得到的特征集合小
题目大意:保证b[i]中每个数互质,给出a[i],然后求1~n的abs(a[i]-b[i])最小。a[i]<=30
思路:首先得到b[i]必然小于60。这个很重要,因为我们枚举的b的集合就是60.首先当b如果都取1,那么最大的abs就是30,所以b可以取得的极限是60.然后我们可以得到60里面的所有的素数,这些素数的个数是17.因此我们发现是状压DP。
首先预处理出1~60的包含素数的集合,然后枚举a[i],枚举1~60,再枚举1~1<<17即可得出答案。
关键:寻找子集范围,寻找变量的最大范围
#include<bits/stdc++.h> using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = + ;
const int u = << ;
struct point{
int val, x, pre;
}dp[maxn][u + ];
int f[maxn];
bool vis[maxn];
vector<int> v;
int n;
int a[maxn];
vector<int> ans; int main(){
for (int i = ; i <= ; i++){
if (!vis[i]){
v.push_back(i);
for (int j = i + i; j <= ; j += i){
vis[j] = true;
}
}
}
int len = v.size();
//f[1] = 1;如果单独变成1了,那么dp时就无法有多个1了。
for (int i = ; i <= ; i++){
int tmp = i;
for (int j = ; j < len; j++){
bool flag = false;
while (tmp % v[j] == ){
tmp /= v[j];
flag = true;
}
if (flag) f[i] |= << (j);
}
}
scanf("%d", &n);
for (int i = ; i <= n; i++) scanf("%d", a + i);
for (int i = ; i < u; i++) dp[][i].val = ;
for (int i = ; i <= n; i++){
for (int j = ; j < u; j++){
dp[i][j].val = inf;
}
}
for (int i = ; i <= n; i++){
for (int j = ; j <= ; j++){
int x = f[j];
for (int k = ; k < u; k++){
if (k & x) continue;
if (dp[i][k | x].val > dp[i - ][k].val + abs(a[i] - j)){
dp[i][k | x].val = dp[i - ][k].val + abs(a[i] - j);
dp[i][k | x].pre = k;
dp[i][k | x].x = j;
}
}
}
} int pre = , mini = dp[n][].val;
for (int i = ; i < u; i++){
if (mini >= dp[n][i].val){
mini = dp[n][i].val;
pre = i;
}
}
//printf("%d\n", dp[n][u - 1].val);
for (int i = n; i > ; i--){
ans.push_back(dp[i][pre].x);
pre = dp[i][pre].pre;
//printf("dp[i][pre].pre = %d\n", dp[i][pre].pre);
//printf("pre = %d\n", pre);
}
reverse(ans.begin(), ans.end());
len = ans.size();
for (int i = ; i < len; i++){
printf("%d%c", ans[i], i == len - ? '\n' : ' ');
}
return ;
}
然后上面的这个47-59行可以有优化成
for (int i = ; i <= n; i++){
for (int j = ; j <= ; j++){
int y = ((~f[j]) & (u - ));
int x = f[j];
for (int k = y; ; k = (k - ) & y){
if (dp[i][k | x].val > dp[i - ][k].val + abs(a[i] - j)){
dp[i][k | x].val = dp[i - ][k].val + abs(a[i] - j);
dp[i][k | x].pre = k;
dp[i][k | x].x = j;
}
if (k == ) break;
}
}
}
就是先筛选出其中本来就不包含和原子集取&的元素,然后通过枚举k,再&可以消去很多种情况,大大减少时间复杂度。
状压DP的总结的更多相关文章
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- 【BZOJ2073】[POI2004]PRZ 状压DP
[BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...
- bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)
数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...
- HDU 1074 Doing Homework (状压dp)
题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
- 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP
[BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...
- 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP
[BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...
- 【BZOJ1087】 [SCOI2005]互不侵犯King 状压DP
经典状压DP. f[i][j][k]=sum(f[i-1][j-cnt[k]][k]); cnt[i]放置情况为i时的国王数量 前I行放置情况为k时国王数量为J #include <iostre ...
随机推荐
- POJ 2986 A Triangle and a Circle(三角形和圆形求交)
Description Given one triangle and one circle in the plane. Your task is to calculate the common are ...
- HDU 4115 Eliminate the Conflict(2-SAT)(2011 Asia ChengDu Regional Contest)
Problem Description Conflicts are everywhere in the world, from the young to the elderly, from famil ...
- Java中I/O流之Object流
Java 中的 object 流:直接将 Object 对象写入或读出 1. serializable 接口:序列化,可以被序列化的,若确实需要将某个类的对象写在硬盘上或网络上,想把他们序列化成一个字 ...
- Deeplearning——Logistics回归
资料来源:1.博客:http://binweber.top/2017/09/12/deep_learning_1/#more——转载,修改更新 2.文章:https://www.qcloud.com/ ...
- oracle 9i 图文安装教程 oracle 9i 安装
我的安装文件是ISO镜像文件,使用Virtual DAEMON Manager v 4.10打开: ora9i-1.iso ora9i-2.iso ora9i-3.iso 首先必须把上面三个镜像文件都 ...
- 什么是Oracle的分区表 (转 作者 陈字文)
假设我们现在正在酝酿经营一家图书馆,最初,我们只有十本书提供给大家来阅读和购买.对于十本书而言,我们可能只需要一个书架格子将其作为保存这十本书的容器就足够了,因为任何一个人都可以很轻松的扫一眼就可以将 ...
- 自学网络 arp_ignore/arp_announce
1)机器上有好几个IP地址,如何让网卡只接收自己IP地址的数据包: 如何只接收自己网卡的数据包 http://www.cnblogs.com/honpey/p/8447819.html 相关的配置ar ...
- [计算机网络] 互联网协议栈(TCP/IP参考模型)各层的主要功能及相应协议
应用层:提供用户与网络间的接口.----HTTP.FTP.SMTP 运输层:进程到进程间的数据传输.---TCP.UDP 网络层:主机到主机之间的数据传输.---IP.选路协议 数据链路层:相邻结点之 ...
- InnoDB,select为啥会阻塞insert?
MySQL的InnoDB的细粒度行锁,是它最吸引人的特性之一. 但是,如<InnoDB,5项最佳实践>所述,如果查询没有命中索引,也将退化为表锁. InnoDB的细粒度锁,是实现在索引记录 ...
- JavaScript 垃圾回收总结
JavaScript 是一门具有自动垃圾收集机制的编程语言,开发人员不必关心内存分配和回收的问题. 以下是对JavaScript的垃圾收集历程总结: 离开作用域的值将被自动标记为可以回收,因此将在垃圾 ...