Looking for Order 压缩DP
来源:互联网 发布:ts文件合并 mac 编辑:程序博客网 时间:2024/06/04 18:20
Girl Lena likes it when everything is in order, and looks for order everywhere. Once she was getting ready for the University and noticed that the room was in a mess — all the objects from her handbag were thrown about the room. Of course, she wanted to put them back into her handbag. The problem is that the girl cannot carry more than two objects at a time, and cannot move the handbag. Also, if he has taken an object, she cannot put it anywhere except her handbag — her inherent sense of order does not let her do so.
You are given the coordinates of the handbag and the coordinates of the objects in some Сartesian coordinate system. It is known that the girl covers the distance between any two objects in the time equal to the squared length of the segment between the points of the objects. It is also known that initially the coordinates of the girl and the handbag are the same. You are asked to find such an order of actions, that the girl can put all the objects back into her handbag in a minimum time period.
The first line of the input file contains the handbag's coordinates xs, ys. The second line contains numbern (1 ≤ n ≤ 24) — the amount of objects the girl has. The followingn lines contain the objects' coordinates. All the coordinates do not exceed 100 in absolute value. All the given positions are different. All the numbers are integer.
In the first line output the only number — the minimum time the girl needs to put the objects into her handbag.
In the second line output the possible optimum way for Lena. Each object in the input is described by its index number (from 1 ton), the handbag's point is described by number 0. The path should start and end in the handbag's point. If there are several optimal paths, print any of them.
0 021 1-1 1
80 1 2 0
1 134 33 40 0
320 1 2 0 3 0
Codeforces (c) Copyright 2010-2014 Mike Mirz
思路: 用状态x: 转化为一串二进制数,位为1 的表示该物品一放回袋子中;dp[x] 维护物品放入袋子走的距离;
有三角形 二边之和大于第三边 ,不妨设 a+b > c 可以推出 a方+b方 + 2*a*b> c方; 所以 a方+b方 不一定大于 C方; 所以不存在贪心的捷径;一次拿俩个还是一次只拿一个只能根据实际物品位置确定;
同时,我们还可以发现,拿物品的先后顺序是没有影响的,先拿 (1,2) ,再拿(3,4),跟先拿(4,3)再拿(1,2)是没有本质区别的;所以我们在搜索时候就可以先找到一位为0的(即此位置i 为0 表示第I 物品尚未拿到包里),在去枚举另一个为0 的,即可进行下一步搜索,退出 i 的枚举~~
正如 (1,2)(3,4) 这个例子:
for(int i=0;i<n;i++)
{
· 发现x的第i位 ==0 ;(假设为1物品)
{
for (枚举跟 i 一起拿的所有可能物品j ) 维护dp[x+(1<<i)+(1<<j)] 进一步搜;
(假设当前找的第一个是2物品)
break ; 退出 i 的循环;
如果没有这个break ,那么可能找到 i=3,然后j=4 把这个(3,4)状态丢进去继续搜,那下一次可能就((3,4),(1,2)) ;然而这个跟 ((1,2),(3,4))是一样的,大大浪费了时间!;
}
}
同理,对一次只能拿一个物品的也一样的道理,因为没有拿的次序问题,所以只要找到状态 x 一个不为0 ,进行计算dp[y] ,进行下一步就可以了;
我用了queue, 从dp[0] 开始搜; 直到dp[1111……11] 结束;
#include<stdio.h>#include<string.h>#include<math.h>#include<string>#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<list>#include<map>#include<set>using namespace std;struct node{ int x,y; node(int x=0,int y=0):x(x),y(y){} void init(){ scanf("%d%d",&x,&y); } node operator - (const node &a) const{ return node(x-a.x,y-a.y); }};int dis2(node a){ return a.x*a.x+a.y*a.y;}const int N=24;node st,a[N+2];int n;int dist[N],pos[N][N];int dp[1<<N];bool vis[1<<N];node pre[1<<N];void deal_dist(){ for(int i=0;i<n;i++) dist[i]=dis2(st-a[i]); for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) pos[i][j]=pos[j][i]=dis2(a[i]-a[j]);// for(int i=0;i<n;i++)// for(int j=0;j<n;j++)// printf("pos [%d %d]=%d\n",i,j,pos[i][j]);}queue<int>que;void deal_min(int &a,int b){ if(a==-1) a=b; else a=min(a,b);}void deal_dp(){ memset(dp,-1,sizeof(dp)); memset(vis,0,sizeof(vis)); dp[0]=0; que.push(0); int tp,y; while(!que.empty()){ int x=que.front();que.pop(); vis[x]=0; if(x==(1<<n)-1) break; for(int i=0;i<n;i++){ if( ( (x>>i) & 1 ) == 0 ){ y=x+(1<<i); tp=dp[y]; deal_min(dp[y],dp[x]+dist[i]*2); if(tp!=dp[y]) pre[y]=node(x,i+1); if(vis[y]==0){ que.push(y); vis[y]=1; } for(int j=i+1;j<n;j++) if( ( (x>>j) & 1 ) == 0 ){ y=x+(1<<i)+(1<<j); tp=dp[y]; deal_min(dp[y],dp[x]+dist[i]+dist[j]+pos[i][j]); if(tp!=dp[y]) pre[y]=node(x,(i+1)*100+(j+1)); if(vis[y]==0){ que.push(y); vis[y]=1; } } break; } } } tp=(1<<n)-1; printf("%d\n",dp[tp]); printf("0"); while(tp){ int id=pre[tp].y; if(id>99){ printf(" %d %d 0",id/100,id%100); } else printf(" %d 0",id); tp=pre[tp].x; } printf("\n");}int main(){// freopen("in.in","r",stdin); st.init(); scanf("%d",&n); for(int i=0;i<n;i++) a[i].init(); deal_dist(); deal_dp(); return 0;}
- Looking for Order 压缩DP
- Codeforces 8C Looking for Order(状态压缩DP)
- CodeForces 8C - Looking for Order 状态压缩DP..DP降低复杂度
- codeforces 8C - Looking for Order 状态DP
- codeforces 8C - Looking for Order 状态DP
- CF 8C Looking for Order(状压dp)
- #8 C. Looking for Order (状压dp + 路径记忆)
- Codeforces 8C Looking for Order(状压DP)
- CodeForces8C Looking for Order【状压】
- Codeforces Beta Round #8 C. Looking for Order 状压DP,路径记录
- CF 8C Looking for Order
- CodeForces 8C-Looking for Order
- Codeforces Beta Round #8 C. Looking for Order CF8C
- looking for internship ...
- looking for thunder link
- Looking back for 2009,looking forward for 2010.
- The life of looking for a job
- unexpected EOF while looking for matching ``'
- 如何同时启动两个tomcat
- 简单的实现向excel单元格中写入数据
- 软件测试技术---单元测试和集成测试
- Funambol服务器源码编译小结
- [模式识别].(希腊)西奥多里蒂斯<第四版>笔记3之__线性分类器
- Looking for Order 压缩DP
- 【Leetcode长征系列】Binary Tree Level Order Traversal
- python 进阶学习之5--入门练习题
- Objective-C中的@property和@synthesize用法
- 一见钟情只在瞬息之间,而对爱大彻大悟却需要很多年
- Socket使用大全
- seq_file文件的内核读取过程
- PKU1751Prime算法
- JAVA 环境的搭建