状压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. 压力测试工具-webbench

    简述 偶然情况下看到一款性能测试工具webbench,看着挺不错的记录一下安装过程,在以后项目上线过程中可以压一压一些页面的并发情况,对项目性能有个大致的了解. 原理 webbench首先fork出多 ...

  2. python函数中的位置参数、默认参数、关键字参数、可变参数区别

    一.位置参数 调用函数时根据函数定义的参数位置来传递参数. #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_d ...

  3. es6从零学习(三):Class的基本用法

    es6从零学习(三):Class的基本用法 一:定义一个类 //定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toSt ...

  4. vue.js学习之 跨域请求代理与axios传参

    vue.js学习之 跨域请求代理与axios传参 一:跨域请求代理 1:打开config/index.js module.exports{ dev: { } } 在这里面找到proxyTable{}, ...

  5. JS判断是IOS还是Android以及如何解决h5打包后在ios下内容与状态栏重叠问题

    h5打包后在ios下内容与状态栏重叠问题: 1:知道设备的类型: var u = navigator.userAgent, app = navigator.appVersion; var isAndr ...

  6. Special Offer! Super Price 999 Bourles!

    Description Polycarpus is an amateur businessman. Recently he was surprised to find out that the mar ...

  7. “Hello World!”团队——Alpha发布用户使用报告

    博客内容: 1.用户体验报告表 2.用户评论截图 3.总结 一.用户体验报告表 用户使用报告 用户序号 用户姓名(化名) 性别 用户职业 使用频次 用户评论 1 小董 女 文学在读硕士 5 1.游戏界 ...

  8. "Hello world!"团队第八次会议

    Scrum会议 今天是我们"Hello world!"团队第八次召开会议,博客内容是: 1.会议时间 2.会议成员 3.会议地点 4.会议内容 5.todo list 6.会议照片 ...

  9. Java学习个人备忘录之文档注释

    文档注释 单行注释用 // 多行注释有两种,第一种是 /* 内容 */,第二种是/** 内容 */. 这两种多行注释的区别是/** 内容 */这种注释可以生成一个该文件的注释文档,下面是演示代码. A ...

  10. 1001 Duplicate Pair

    1.题目戳这里 2.代码: #include<stdio.h> #include<string.h> int main() { int n; while(scanf(" ...