题目描述

莫莉斯·乔是圣域里一个叱咤风云的人物,他凭借着自身超强的经济头脑,牢牢控制了圣域的石油市场。

圣域的地图可以看成是一个n*m的矩阵。每个整数坐标点(x , y)表示一座城市\(( 1\le x\le n,1\le y\le m)\)。两座城市间相邻的定义为:对于城市(Ax, Ay)和城市(Bx, By),满足 (Ax - Bx)^2 + (Ay - By)^2 = 1(Ax−Bx)2+(Ay−By)2=1 。

由于圣域的石油贸易总量很大,莫莉斯意识到不能让每笔石油订购单都从同一个油库里发货。为了提高效率,莫莉斯·乔决定在其中一些城市里建造油库,最终使得每一个城市X都满足下列条件之一:

1.该城市X内建有油库,

2.某城市Y内建有油库,且城市X与城市Y相邻。

与地球类似,圣域里不同城市间的地价可能也会有所不同,所以莫莉斯想让完成目标的总花费尽可能少。如果存在多组方案,为了方便管理,莫莉斯会选择建造较少的油库个数。

输入输出格式

输入格式:

第一行两个正整数n,m \(( n \times m \le 50 且 m\le n)\),表示矩阵的大小。

接下来一个n行m列的矩阵F, \(F_{i, j}\) 表示在城市(i,j)建造油库的代价。

输出格式:

输出两个数,建造方案的油库个数和方案的总代价。

其中数据范围是

对于30%数据满足 \(n \times m \le 25\) ;

对于100%数据满足\(n \times m \le 50,0 \le F_{i, j} \le100000\)

看一下这个数据范围,不难得出,m<=7

所以可以直接进行dp

首先我们先预处理一下cost[i][j]表示在第i行,建造j这个状态的油库需要的最小代价是多少

num[j]是j这个状态有几个油库(也就是有几个一) 可以直接用_builtin_popcount()来算

QAQ然后考虑dp

因为第i行的状态只能转移到i+1的状态转移过来

所以f[i][j][k]表示前i-1行的已经都能够合法,第i行的状态是j,第i-1行的状态时k的最小花费

同时g[i][j][k]则表示对应状态的油库数量

首先我们考虑转移条件~~

因为是要求前i行的状态合法,才能转移到i+1

所以要求 \((p| j | k|{j << 1} |{j >> 1}) \&{2^m-1}\ ==\ {2^m
-1}\)



这个条件也就是对应的是第i行是所有的位置都是合法的

然后考虑对于\(f[i][j][k]\)能转移到哪个状态

我们在转移的时候,枚举j,k,p



\(f[i+1][p][j]=f[i][j][k]+cost[i+1][p]\)



\(g[i+1][p][j]=g[i][j][k]+num[p]\)

同时当上述的f在转移时相等的时的时候,我们也可以考虑更新g

不懂的可以看一下代码

  1. if (((j|k|p|(j<<1)|(j>>1))&((1 << m)-1))==((1 << m)-1))
  2. {
  3. if (f[i][j][k]+sum[i+1][p]<f[i+1][p][j])
  4. {
  5. f[i+1][p][j]=f[i][j][k]+sum[i+1][p];
  6. g[i+1][p][j]=g[i][j][k]+num[p];
  7. }
  8. else
  9. {
  10. if (f[i][j][k]+sum[i+1][p]==f[i+1][p][j])
  11. {
  12. g[i+1][p][j]=min(g[i+1][p][j],g[i][j][k]+num[p]);
  13. }

QWQ最后的答案就是

f[n+1][0][i] 以及对应最小费用的最小油库个数

上代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<cstdlib>
  7. #include<queue>
  8. #include<map>
  9. #include<vector>
  10. using namespace std;
  11. inline int read()
  12. {
  13. int x=0,f=1;char ch=getchar();
  14. while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  15. while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  16. return x*f;
  17. }
  18. const int maxn = 210;
  19. int a[61][61];
  20. int f[61][maxn][maxn];
  21. int g[61][maxn][maxn];
  22. int sum[61][maxn];
  23. int n,m;
  24. int num[maxn];
  25. int ans1=1e9;
  26. int ans2=1e9;
  27. int main()
  28. {
  29. scanf("%d%d",&n,&m);
  30. for (int i=1;i<=n;i++)
  31. for (int j=1;j<=m;j++)
  32. a[i][j]=read();
  33. for (int i=1;i<=n;i++)
  34. {
  35. for (int j=0;j<(1 << m);j++)
  36. {
  37. for (int k=1;k<=m;k++)
  38. {
  39. if (j&(1 << (k-1))) {
  40. sum[i][j]+=a[i][k];
  41. }
  42. }
  43. }
  44. }
  45. memset(f,127/3,sizeof(f));
  46. memset(g,127/3,sizeof(g));
  47. for (int j=0;j<(1 << m);j++) num[j]=__builtin_popcount(j);
  48. for (int i=0;i<(1 << m);i++)
  49. {
  50. f[1][i][0]=sum[1][i];
  51. g[1][i][0]=num[i];
  52. }
  53. for (int i=1;i<=n;i++)
  54. {
  55. for (int j=0;j<(1 << m);j++)
  56. for (int k=0;k<(1 << m);k++)
  57. {
  58. for (int p=0;p<(1 << m);p++)
  59. {
  60. if (((j|k|p|(j<<1)|(j>>1))&((1 << m)-1))==((1 << m)-1))
  61. {
  62. if (f[i][j][k]+sum[i+1][p]<f[i+1][p][j])
  63. {
  64. f[i+1][p][j]=f[i][j][k]+sum[i+1][p];
  65. g[i+1][p][j]=g[i][j][k]+num[p];
  66. }
  67. else
  68. {
  69. if (f[i][j][k]+sum[i+1][p]==f[i+1][p][j])
  70. {
  71. g[i+1][p][j]=min(g[i+1][p][j],g[i][j][k]+num[p]);
  72. }
  73. }
  74. }
  75. }
  76. }
  77. }
  78. for (int i=0;i<(1 << m);i++)
  79. {
  80. if (ans1>f[n+1][0][i])
  81. {
  82. ans1=f[n+1][0][i];
  83. ans2=g[n+1][0][i];
  84. }
  85. else
  86. {
  87. if (ans1==f[n+1][0][i])
  88. ans2=min(ans2,g[n+1][0][i]);
  89. }
  90. }
  91. cout<<ans2<<" "<<ans1;
  92. return 0;
  93. }

这大概是QWQ第一篇makedown的博客 嗯

luogu3888 GDOI2014拯救莫里斯 (状压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< ...

随机推荐

  1. RabitMq过期时间TTL

    第一种:给消息设置过期时间 启动一个插件 @Bean public DirectExchange DirectExchange() { return new DirectExchange(" ...

  2. Golang slice作为函数参数

    slice底层其实是一个结构体,len.cap.array分别表示长度.容量.底层数组的地址,当slice作为函数的参数传递的时候,跟普通结构体的传递是没有区别的:如果直接传slice,实参slice ...

  3. redis连接池 go-redis

    为什么使用连接池? 首先Redis也是一种数据库,它基于C/S模式,因此如果需要使用必须建立连接,稍微熟悉网络的人应该都清楚地知道为什么需要建立连接,C/S模式本身就是一种远程通信的交互模式,因此Re ...

  4. Mysql You can't specify target table 'newsalrecord' for update in FROM clause

    这个问题是不能先select出同一表中的某些值,再update这个表(在同一语句中),即不能依据某字段值做判断再来更新某字段的值.解决办法就是建立个临时的表.

  5. MySQL 源码安装规范

    一 .目录规划 MySQL 的目录包括 base 目录和 data 目录,base 目录存放软件文件,每个版本的软件单 独一个目录,例如/usr/local/mysql/mysql5.6.19.dat ...

  6. ❤️用武侠小说的形式来阅读LinkedList的源码,绝了!

    一.LinkedList 的剖白 大家好,我是 LinkedList,和 ArrayList 是同门师兄弟,但我俩练的内功却完全不同.师兄练的是动态数组,我练的是链表. 问大家一个问题,知道我为什么要 ...

  7. noip模拟测试50

    考试过程:开题顺序1,2,3,做T1的时候我想到了要求的东西,就是分成尽量少的段使得每段之和>=k,但是我不会求,就打了个暴力走了,然后看T2,这题我觉得和之前做过的一道题比较像,因为我觉得\( ...

  8. Jenkins(7)- 解决Linux下忘记Jenkins密码

    如果想从头学起Jenkins的话,可以看看这一系列的文章哦 https://www.cnblogs.com/poloyy/category/1645399.html admin密码未更改情况下 进入\ ...

  9. ubantu硬盘不足,无法启动

    我的ubantu虚拟机经过我一顿操作后,就起不来了.然后经过多方询问,广集天下良方,最终发现是由于分配的硬件空间不足导致的.现象如下: 通过查看 root@ubantu:/snap# df -h Fi ...

  10. PyRevit开发第一步:获取Revit文档Document

    1.安装PythonShell插件 PythonShell 2018 插件下载 交流QQ群: 17075104 新建项目后,运行功能Python Shell, 在弹出的窗口中复制或输入以下引用代码模块 ...