HDU4385Moving Bricks【状压DP】

Moving Bricks

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 724    Accepted Submission(s): 280

Problem Description

Brickgao used to be a real tall, wealthy, handsome man and you might know him well. If you don‘t, please draw attention to the details below.
Brickgao tried his fortune in investment of golden bricks with his two partners LS and Jne. Because he knew little about investment he gave his total trust and bank savings to his two partners who looked smart. 
However, due to the bad luck and lack of business skills, LS and Jne used up Brickgao‘s fund, and nothing in return. Their investment failed and the three become diaosi. 
Brickgao had no other choice but to earn a living as a construction worker and he found his place on a building site moving bricks which of course was not golden ones. There were many brick fragment scattered on the site and workers had to move them to the building that under construction. Brickgao was made to cope with the task.
The problem is that the Brickgao couldn’t carry more than two bricks at a time since they were too heavy. Also, if he had taken a brick, he couldn’t put it anywhere except the goal building — his inherent sense of order does not let him do so.
You are given N pairs of coordinates of the bricks and the coordinates of the goal building. It is known that the Brickgao covers the distance between any two points in the time equal to the squared length of the segment between the points. It is also known that initially the coordinates of the Brickgao and the goal building are the same. You are asked to find such an order of bricks, that the Brickgao could move all the bricks to the building in a minimum time period. You can assume the no two bricks shared the same coordinates. If more than one optimum moving sequence Brickgao could find, he would choose the smallest lexicographic one because of the inherent sense of order.

Input

The first line of the input file contains an integer T which indicates the number of test cases. The first line of each case contains the building‘s coordinates x ,y. The second line contains number N (1<= N < 20) — the amount of bricks on the building site. The following N lines contain the bricks‘ coordinates. All the coordinates do not exceed 100 in absolute value. All the given positions are different. All the numbers are integer.

Output

For each test case, first you should print "Case x:" in a line, where x stands for the case number started with 1. Then two lines follow: the first line output the only number — the minimum time Brickgao needed to move the bricks to building, and the second line output the optimum order for Brickgao to move the bricks. Each brick in the input is described by its index number (from 1 to N).

Sample Input

2
0 0
2
1 1
-1 1
1 1
3
4 3
3 4
0 0

Sample Output

Case 1:
8
1 2
Case 2:
32
1 2 3

Hint

In the first test, Brickgao gets brick 1 and brick 2 and returns to the building.
In the second test, Brickgao first moves brick 1 and brick 2 to the building and then gets the third and returns to the building.

Author

WHU

Source

2012 Multi-University Training Contest 9

这个题说实话也卡了很多天了  原因是 字典序最小之前没有处理好

之前做过一个很像的题  是一次训练赛德题

那题是这样的  告诉你n个点n 《= 15  的坐标  问一笔画下来最少的路程

那个是这样的dp[i][j]代表状态为i  以第j个点位结尾的最短路

由于|的性质  所以直接往后枚举状态进行转移就可以了

这个题很像

题意是有n个点n<20  每次从初始点出发取回一个或两个点上的石头   取回需要的价值是 距离的平方和

然后问取回所有点的最小价值

这个题dp[i]代表到大i状态的最短路  然后用一个数组表示最短路的最后一个点是啥

最后 由于每次只取回一或者两个点  只要把它拍一下序就好了

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6
  7 const int maxn = 20;
  8 int dp[1 << maxn];
  9 int x[maxn], y[maxn];
 10 int dist[maxn][maxn];
 11 int n, t;
 12 int fa[maxn];
 13
 14 struct Node {
 15     int pr;
 16     int x1, x2;
 17 }node[1 << maxn];
 18 struct Ans {
 19     int flag;
 20     int x1, x2;
 21 }ans[maxn];
 22 bool cmp(Ans a1, Ans a2) {
 23     return a1.x1 < a2.x1;
 24 }
 25 int xx[1 << maxn];
 26 int an[maxn];
 27
 28 void init() {
 29     for(int i = 0; i <= n; i++) {
 30         for(int j = i; j <= n; j++) {
 31             dist[i][j] = dist[j][i] = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]);
 32             dist[j][i] = dist[i][j];
 33         }
 34     }
 35 }
 36
 37 void DP() {
 38     memset(dp, 0x3f, sizeof(dp));
 39     dp[0] = 0; xx[0] = 0;
 40     fa[0] = 0;
 41     int Max = 1 << n;
 42     for(int i = 0; i < Max; i++) {
 43         if(dp[i] > 1000000000) continue;
 44         for(int j = 1; j <= n; j++) {
 45             if((i & ( 1 << ( j - 1 ) ) ) == 0 ) {
 46                 int num = i | ( 1 << ( j - 1 ) );
 47                 if(dp[num] > dp[i] + dist[j][0] * 2) {
 48                     dp[num] = dp[i] + dist[j][0] * 2;
 49                     xx[num] = j;
 50                     node[num] = (Node) { i, 0, 0 };
 51                 }
 52             }
 53         }
 54         for(int j = 1; j <= n; j++) {
 55             for(int k = j + 1; k <= n; k++) {
 56                 if((i & ( 1 << ( j - 1 ) ) ) == 0 && ( i & ( 1 << ( k - 1) ) ) == 0) {
 57                     int num = i | ( 1 << ( j - 1 ) );
 58                     num |= ( 1 << ( k - 1) );
 59                     if(dp[num] > dp[i] + dist[0][j] + dist[j][k] + dist[k][0]) {
 60                         dp[num] = dp[i] + dist[0][j] + dist[j][k] + dist[k][0];
 61                         xx[num] = j;
 62                         node[num] = (Node) { i, 1, k };
 63                     }
 64                 }
 65             }
 66         }
 67     }
 68 }
 69
 70 void P() {
 71     int Max = 1 << n;
 72     printf("%d\n", dp[Max - 1]);
 73     int id = Max - 1;
 74     int cnt = 0;
 75     for(int i = 1; i <= n; i++) {
 76         if(node[id].x1 == 0) {
 77             ans[cnt++] = (Ans) { 1, xx[id], 0 };
 78         } else {
 79             ans[cnt++] = (Ans) { 2, min(xx[id],node[id].x2), max(xx[id],node[id].x2)};
 80             i++;
 81         }
 82         id = node[id].pr;
 83     }
 84     sort(ans, ans + cnt, cmp);
 85     int cn = 0;
 86     for(int i = 0; i < cnt; i++) {
 87         if(ans[i].flag == 1) {
 88             an[cn++] = ans[i].x1;
 89         } else {
 90             an[cn++] = ans[i].x1;
 91             an[cn++] = ans[i].x2;
 92         }
 93     }
 94     for(int i = 0; i < cn; i++) {
 95         printf(i == 0 ? "%d" : " %d", an[i]);
 96     } puts("");
 97 }
 98
 99 int main() {
100     scanf("%d",&t);
101     for(int kase = 1; kase <= t; kase++) {
102         scanf("%d %d",&x[0], &y[0]);
103         scanf("%d",&n);
104         for(int i = 1; i <= n; i++) {
105             scanf("%d %d",&x[i], &y[i]);
106         }
107         init();
108         DP();
109         printf("Case %d:\n", kase);
110         P();
111     }
112     return 0;
113 }

时间: 2024-09-30 01:52:11

HDU4385Moving Bricks【状压DP】的相关文章

ZOJ3305Get Sauce 状压DP,

状压DP的题目留个纪念,首先题意一开始读错了,搞了好久,然后弄好了,觉得DFS可以,最后超时,修改了很久还是超时,没办法看了一下n的范围,然后觉得状压可以,但是没有直接推出来,就记忆化搜索了一下,可是一直错,莫名奇妙,然后没办法看了一下题解,发现了下面这个比较好的方法,然后按照这个方程去推,然后敲,也是WA了好多把,写的太搓了,没人家的清楚明了,唉~也算是给自己留个纪念,状压一直做的都不太好~唉~还好理解了, 参考了  http://blog.csdn.net/nash142857/articl

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in

HDU5816 Hearthstone(状压DP)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collectible card game from Blizzard Entertainment. Strategies and luck are the most important factors in this game. When you suffer a desperate situation an

HDU 4336 容斥原理 || 状压DP

状压DP :F(S)=Sum*F(S)+p(x1)*F(S^(1<<x1))+p(x2)*F(S^(1<<x2))...+1; F(S)表示取状态为S的牌的期望次数,Sum表示什么都不取得概率,p(x1)表示的是取x1的概率,最后要加一因为有又多拿了一次.整理一下就可以了. 1 #include <cstdio> 2 const int Maxn=23; 3 double F[1<<Maxn],p[Maxn]; 4 int n; 5 int main() 6

Travel(HDU 4284状压dp)

题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走,一个城市只能工作一次,问pp是否能游览n个城市回到城市1. 分析:这个题想到杀怪(Survival(ZOJ 2297状压dp) 那个题,也是钱如果小于0就挂了,最后求剩余的最大钱数,先求出最短路和 Hie with the Pie(POJ 3311状压dp) 送披萨那个题相似. #include <

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

简单的状压dp... dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s . 考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king ) 我有各种预处理所以 code 的方程和这有点不一样 ------------------------------------------------

BZOJ 1072 排列 状压DP

题意:链接 方法:状压DP? 题解:这题其实没啥好写的,不算很难,推一推就能搞出来. 首先看到这个问题,对于被d整除这个条件,很容易就想到是取余数为0,所以想到可能状态中刚开始含有取余数. 先说我的第一个想法,f[i][j]表示选取i个数且此时的mod为j,这样的思想是第一下蹦出来的,当时想的就是在线来搞最终的答案.不过转瞬即发现,这TM不就是暴力吗魂淡!并没有什么卵用,于是开始想这个状态可不可以做什么优化. 显然第二维的j并不需要太大的优化,暂且先将其搁置一边,来考虑第一维的i怎么优化. 把滚

COdeforces#417D Cunning Gena(状压DP)

A boy named Gena really wants to get to the "Russian Code Cup" finals, or at least get a t-shirt. But the offered problems are too complex, so he made an arrangement with his n friends that they will solve the problems for him. The participants

UVA 10817 Headmaster&#39;s Headache 状压DP

记录两个状态S1,S2分别记录哪些课程被1个人教过或2个人教过,然后记忆化搜索 UVA - 10817 Headmaster's Headache Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spr