状压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即可得出答案。

关键:寻找子集范围,寻找变量的最大范围

  1. #include<bits/stdc++.h>
  2.  
  3. using namespace std;
  4. const int inf = 0x3f3f3f3f;
  5. const int maxn = + ;
  6. const int u = << ;
  7. struct point{
  8. int val, x, pre;
  9. }dp[maxn][u + ];
  10. int f[maxn];
  11. bool vis[maxn];
  12. vector<int> v;
  13. int n;
  14. int a[maxn];
  15. vector<int> ans;
  16.  
  17. int main(){
  18. for (int i = ; i <= ; i++){
  19. if (!vis[i]){
  20. v.push_back(i);
  21. for (int j = i + i; j <= ; j += i){
  22. vis[j] = true;
  23. }
  24. }
  25. }
  26. int len = v.size();
  27. //f[1] = 1;如果单独变成1了,那么dp时就无法有多个1了。
  28. for (int i = ; i <= ; i++){
  29. int tmp = i;
  30. for (int j = ; j < len; j++){
  31. bool flag = false;
  32. while (tmp % v[j] == ){
  33. tmp /= v[j];
  34. flag = true;
  35. }
  36. if (flag) f[i] |= << (j);
  37. }
  38. }
  39. scanf("%d", &n);
  40. for (int i = ; i <= n; i++) scanf("%d", a + i);
  41. for (int i = ; i < u; i++) dp[][i].val = ;
  42. for (int i = ; i <= n; i++){
  43. for (int j = ; j < u; j++){
  44. dp[i][j].val = inf;
  45. }
  46. }
  47. for (int i = ; i <= n; i++){
  48. for (int j = ; j <= ; j++){
  49. int x = f[j];
  50. for (int k = ; k < u; k++){
  51. if (k & x) continue;
  52. if (dp[i][k | x].val > dp[i - ][k].val + abs(a[i] - j)){
  53. dp[i][k | x].val = dp[i - ][k].val + abs(a[i] - j);
  54. dp[i][k | x].pre = k;
  55. dp[i][k | x].x = j;
  56. }
  57. }
  58. }
  59. }
  60.  
  61. int pre = , mini = dp[n][].val;
  62. for (int i = ; i < u; i++){
  63. if (mini >= dp[n][i].val){
  64. mini = dp[n][i].val;
  65. pre = i;
  66. }
  67. }
  68. //printf("%d\n", dp[n][u - 1].val);
  69. for (int i = n; i > ; i--){
  70. ans.push_back(dp[i][pre].x);
  71. pre = dp[i][pre].pre;
  72. //printf("dp[i][pre].pre = %d\n", dp[i][pre].pre);
  73. //printf("pre = %d\n", pre);
  74. }
  75. reverse(ans.begin(), ans.end());
  76. len = ans.size();
  77. for (int i = ; i < len; i++){
  78. printf("%d%c", ans[i], i == len - ? '\n' : ' ');
  79. }
  80. return ;
  81. }

然后上面的这个47-59行可以有优化成

  1. for (int i = ; i <= n; i++){
  2. for (int j = ; j <= ; j++){
  3. int y = ((~f[j]) & (u - ));
  4. int x = f[j];
  5. for (int k = y; ; k = (k - ) & y){
  6. if (dp[i][k | x].val > dp[i - ][k].val + abs(a[i] - j)){
  7. dp[i][k | x].val = dp[i - ][k].val + abs(a[i] - j);
  8. dp[i][k | x].pre = k;
  9. dp[i][k | x].x = j;
  10. }
  11. if (k == ) break;
  12. }
  13. }
  14. }

就是先筛选出其中本来就不包含和原子集取&的元素,然后通过枚举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. 六: Image Viewer 离线镜像查看器

    参考:http://hadoop.apache.org/docs/r2.6.3/hadoop-project-dist/hadoop-hdfs/HdfsImageViewer.html   离线镜像查 ...

  2. Python中的list

    list的创建 1 字面量 >>>L = [1, 2, 3] [1, 2, 3] 2 通过iterable可迭代对象,比如str对象,range对象,map对象 >>&g ...

  3. 自测之Lesson13:共享内存

    题目:创建一个64K的共享内存. 实现代码: #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> ...

  4. Coprime Sequence(前后缀GCD)

    Description Do you know what is called ``Coprime Sequence''? That is a sequence consists of $n$ posi ...

  5. Thunder团队第一周 - Scrum会议2

    Scrum会议2 小组名称:Thunder 项目名称:待定 Scrum Master:李传康 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康(M ...

  6. java利用POI实现读取Word并获取指定样式的文本

    import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.model.StyleDescription; import o ...

  7. win10 死机

    其实Win10系统还是不错的,如果你的电脑升级Win10后中招经常死机,可以用下面的方案来应对. 1.下载安装支持兼容Win10的软件版本,下载软件之前看一下兼容列表里是否有Win10系统.虽然Win ...

  8. 什么是POJO模式

    1.     什么是POJO POJO的名称有多种,pure old java object .plain ordinary java object 等. 按照Martin Fowler的解释是“Pl ...

  9. YaoLingJump开发者日志(七)

      LGame用起来真是各种蛋疼,插背景都可以显示不出来.在屏幕结束后释放资源,重载该屏幕时再setbackground也不行,直接用Lpaper当background更不行,会把tilemap上的东 ...

  10. QT分析之网络编程

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201002842553382/ 首先对Windows下的网络编程总结一下: 如果是服务器 ...