要点

  • 设\(f[i][j][k]\)为经过点\((i,j)\)且包含点集\(k\)的最小代价,其中k是指景点集合的枚举。
  • 考虑有两种情况:1.点\((i,j)\)作为关键点连接了两个子集时\(f[i][j][k]\)可以得到最小,有\(f[i][j][k]=f[i][j][k_1]+f[i][j][k_2]-a[i][j],\ k_1|k_2=k\);2.点\((i,j)\)作为主干道发展出来的枝叶时\(f[i][j][k]\)可以得到最小,那么它是它的邻居发展过来的,spfa跑一下即可。
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <queue>
  6. using namespace std;
  7. const int inf = 0x3f3f3f3f;
  8. const int xx[] = {0, 0, -1, 1};
  9. const int yy[] = {1, -1, 0, 0};
  10. int N, M, K, a[11][11];
  11. int f[11][11][1 << 11], pre[11][11][1 << 11][3], vis[11][11];
  12. queue< pair<int, int> > Q;
  13. void dfs(int i, int j, int U) {
  14. if (!U) return;
  15. vis[i][j] = 1;
  16. int a = pre[i][j][U][0], b = pre[i][j][U][1], c = pre[i][j][U][2];
  17. dfs(a, b, c);
  18. if (i == a && j == b) dfs(a, b, c ^ U);
  19. }
  20. void output() {
  21. for (int i = 1; i <= N; i++) {
  22. for (int j = 1; j <= M; j++)
  23. if (!a[i][j]) putchar('x');
  24. else if (vis[i][j]) putchar('o');
  25. else putchar('_');
  26. puts("");
  27. }
  28. }
  29. int main() {
  30. scanf("%d %d", &N, &M);
  31. for (int i = 1; i <= N; i++)
  32. for (int j = 1; j <= M; j++) {
  33. for (int k = 0; k < (1 << 10); k++) {
  34. f[i][j][k] = inf;
  35. }
  36. scanf("%d", &a[i][j]);
  37. if (!a[i][j]) {
  38. f[i][j][1 << (K++)] = 0;
  39. }
  40. }
  41. for (int U = 1; U < (1 << K); U++) {
  42. memset(vis, 0, sizeof vis);
  43. //作为枝干的转移
  44. for (int i = 1; i <= N; i++)
  45. for (int j = 1; j <= M; j++) {
  46. for (int k = U & (U - 1); k; k = U & (k - 1)) {//枚举二进制真子集
  47. int tmp = f[i][j][k] + f[i][j][k ^ U] - a[i][j];
  48. if (tmp < f[i][j][U]) {
  49. f[i][j][U] = tmp;
  50. pre[i][j][U][0] = i;
  51. pre[i][j][U][1] = j;
  52. pre[i][j][U][2] = k;
  53. }
  54. }
  55. if (f[i][j][U] < inf) Q.push({i, j}), vis[i][j] = 1;
  56. }
  57. //作为树枝的转移
  58. while (Q.size()) {
  59. int x = Q.front().first, y = Q.front().second; Q.pop();
  60. vis[x][y] = 0;
  61. for (int t = 0; t < 4; t++) {
  62. int nx = x + xx[t], ny = y + yy[t];
  63. if (nx < 1 || nx > N || ny < 1 || ny > M) continue;
  64. if (f[nx][ny][U] > f[x][y][U] + a[nx][ny]) {
  65. f[nx][ny][U] = f[x][y][U] + a[nx][ny];
  66. pre[nx][ny][U][0] = x;
  67. pre[nx][ny][U][1] = y;
  68. pre[nx][ny][U][2] = U;
  69. if (!vis[nx][ny]) Q.push({nx, ny}), vis[nx][ny] = 1;
  70. }
  71. }
  72. }
  73. }
  74. for (int i = 1; i <= N; i++)
  75. for (int j = 1; j <= M; j++)
  76. if (!a[i][j]) {
  77. memset(vis, 0, sizeof vis);
  78. dfs(i, j, (1 << K) - 1);
  79. printf("%d\n", f[i][j][(1 << K) - 1]);
  80. output();
  81. return 0;
  82. }
  83. }

BZOJ2595(状压dp)的更多相关文章

  1. BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*

    BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...

  2. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. HDU 1074 Doing Homework (状压dp)

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

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

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

随机推荐

  1. leetcode 66. Plus One(高精度加法)

    Given a non-negative number represented as an array of digits, plus one to the number. The digits ar ...

  2. Linux 文本的^M问题

    很多人在windows中使用文本编辑器编辑好文本后,传送到linux系统后,使用vi工具打开后发现每一行文本最后都有一个^M号,原因是: 在DOS使用的换行符为 \r\n,我们称为CR(\r)与LF( ...

  3. HihoCoder1642 : 三角形面积和([Offer收割]编程练习赛37)(求面积)(扫描线||暴力)(占位)

    描述 如下图所示,在X轴上方一共有N个等腰直角三角形.这些三角形的斜边与X轴重合,斜边的对顶点坐标是(Xi, Yi). (11,5) (4,4) /\ /\(7,3) \ / \/\/ \ / /\/ ...

  4. 【Python】python2.7 安装配置OpenCV2

    环境:Ubuntu16.04 anaconda Python2.7 opencv2.4.13 安装opencv后 import cv2 遇到错误信息: No module named cv2 安装op ...

  5. matlab函数 bwperim

    功能:查找二值图像的边缘. 用法: BW2 = bwperim(BW1) BW2 = bwperim(BW1,conn) BW2 = bwperim(BW1,conn)表示从输入图像BW1中返回只包括 ...

  6. 如何解决 Matlab 画图时中文显示乱码的问题?

    使用的是win10系统,从前几个月某一天,我的matlab的figure里的中文都变成了口口.很是郁闷,还以为是动到了什么配置引起的. 前几天更新了matlab 2018b,发现还有这个问题.就觉得不 ...

  7. Unity查找Editor下Project视图中特定的资源

    [MenuItem("Tools/Check Text Count")] public static void CheckText () { //查找指定路径下指定类型的所有资源, ...

  8. CSS实现三角形图标原理解析

    CSS实现三角形图标原理解析: border边框语法: border 四条边框设置border-left 设置左边框,一般单独设置左边框样式使用border-right 设置右边框,一般单独设置右边框 ...

  9. GitBook 入门学习

    一.什么是 Gitbook GitBook 是一个基于 Node.js 的命令行工具,支持 Markdown 和 AsciiDoc 两种语法格式,可以输出 HTML.PDF.eBook 等格式的电子书 ...

  10. echarts学习的一些笔记

    工具栏组件 Show 是否显示 Feature 具体显示的功能 saveAslmage  保存图片 Restore 还原 dataZoom  缩放视图 magicType 动态类型切换 toltip组 ...