状压dp的标志

①数据小 ②通过题目所给出的条件以后得到的特征集合小

一:CF259div2 D:

题目大意:保证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的总结的更多相关文章

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

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

  2. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  3. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  4. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  5. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  6. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

  7. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

  8. 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP

    [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...

  9. 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

    [BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M< ...

  10. 【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 ...

随机推荐

  1. ZOJ 2532 Internship(最大流找关键割边)

    Description CIA headquarter collects data from across the country through its classified network. Th ...

  2. js经典试题之数据类型

    js经典试题之数据类型 1:输出"B" + "a" + + "B" + "a"的值: 答案:BaNaNa. 分析:因为+ ...

  3. 20172305 2018-2019-1 《Java软件结构与数据结构》第一周学习总结

    20172305 2018-2019-1 <Java软件结构与数据结构>第一周学习总结 教材学习内容总结 本周内容主要为书第一章和第二章的内容: 第一章 软件质量: 正确性(软件达到特定需 ...

  4. MFC消息处理

    1.MFC窗口如何与AfxWndProc建立联系. 当一个新的CWnd派生类创建时,在调用CWnd::CreateEx()过程中,MFC都会安装AfxCbtFilterHook().这个Hook将拦截 ...

  5. 如何彻底解决adb 5037端口被占用

    在进行安卓开发的时候是不是经常碰到adb端口被占用的情况? 解决这个问题的方法很简单,只需要设置一个系统环境变量就可以搞定. 设置方法: 增加系统环境变量变量名称:ADNROID_ADB_SERVER ...

  6. PHPcmsv9 还原数据库 操作步骤

    相比dedecms,相同之处:模版好制作,都是开源.不同之处:pc貌似有更好的 负载能力. 言归正传,这两天在捣鼓phpcmsv9程序,但是本地调试好了之后,无论是通过打包方式,还是 转移数据的方式. ...

  7. MySQL必备命令

    来源:http://www.cnblogs.com/liushuijinger/p/3381775.html 今天跟大家分享一下MySQL从连接到具体操作的一系列常用命令.可能有的人觉得现在有很多可视 ...

  8. Gradle sync failed: Failed to find Build Tools revision 26.0.2的解决办法

    说明在android studio中没有 build tools 的26.0.2的版本,你确认一下,是否是这样: 点击==>android studio的菜单栏中Tools==>andro ...

  9. timer实现

    实现一个 timer 前段时间写过一篇 blog 谈到 用 timer 驱动游戏 的一个想法.当 timer 被大量使用之后,似乎自己实现一个 timer 比用系统提供的要放心一些.最近在重构以前的代 ...

  10. 2011 Multi-University Training Contest 4 - Host by SDU

    A.Color the Simple Cycle(polya计数+字符串匹配) 此题的难点在于确定置换的个数,由a[i+k]=a[i], e[i+k]=e[i]联想到KMP. 于是把原串和原串扩大两倍 ...