HDU 4892 状压dp

来源:互联网 发布:c语言控制机械手 编辑:程序博客网 时间:2024/06/06 07:47

[BestCoder Round #5]冠军的奖励是小米3手机一部
恭喜福州大学杨楠获得[BestCoder Round #4]冠军(iPad Mini一部)
《BestCoder用户手册》下载

Defence of the Trees

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 224    Accepted Submission(s): 51
Special Judge


Problem Description
There are n trees (each of them can be considered as a point) on a two-dimensional coordinate system. There are k categories of trees, category of the ith tree are represented by Ai. There are also m stumps (each of them can be considered as a point, too) on this two-dimensional coordinate system. Stumps can be connected with straight wires.

Your task is to connect some of the stumps by wires to build exactly one simple polygon (that is, a polygon without self-intersection and degeneration) which contains trees of all k categories inside. Meanwhile, in order to save money, you should make the total length of wires as short as possible. Your task is to calculate the shortest total length of wires, or to determine that there is no solutions.
 

Input
There are several testcases, please process till EOF.

In each testcases:
First one line, three numbers n, m, k. Following n lines contains n 2D-coordinates describing each tree. Next one line contains n number, where ith number Ai denotes ith tree's category. Next m lines describe the coordinates of stumps, you may assume that there is no trees lying on segments between any two stumps.

All input will be integer, and absolute value of them will be less than 23333, 1 ≤ n ≤ 300, 1 ≤ m ≤ 40, 1 ≤ k ≤ 6,1 ≤ Ai ≤ k.In about 90% of testcases,m ≤ 10.
 

Output
For each testcase, print one line, if there is no solutions, Output "Impossible" (without quotes), else output a real number indicating the minimal total length. Your answer will be considered correct if and only if the absolute error or relative error are less than 10-6.
 

Sample Input
2 4 1 0 0 2 0 1 1 1 -1 1 1 -3 -1 5 1 2 4 2 0 0 2 0 1 2 1 -1 1 1 -3 -1 5 1
 

Sample Output
10.472135955000 16.944271909999
 

Author
Fudan University

题意:

有n颗树,总共有k种种类,每棵树有一个种类,有m个木桩,要选一些木桩连起来,使得包含所有的树的种类,并且连线最短。

由于k<=6,数据很小,一看就是状压dp, 把m个点的三角形全部找出来,然后把三角形内部k个种类的状态全部找出来,然后就是三角形合并,每次合并都会是

两边的周长减去公共边的长度的2倍,然后状态合并,

用类似与最短路的方法求答案。

搞了半天,发现spfa有问题,我们需要记录k的状态,还需要记录当前周长的状态,由于一个状态可能有多个周长,用数组记录也不大方便,所以把它拧成一个节点,丢进优先队列里,这样合并就没问题了,

代码:

/* ***********************************************Author :rabbitCreated Time :2014/8/15 10:13:28File Name :5.cpp************************************************ */#pragma comment(linker, "/STACK:102400000,102400000")#include <stdio.h>#include <iostream>#include <algorithm>#include <sstream>#include <stdlib.h>#include <string.h>#include <limits.h>#include <string>#include <time.h>#include <math.h>#include <queue>#include <stack>#include <set>#include <map>using namespace std;#define INF 1e15#define eps 1e-9#define pi acos(-1.0)typedef long long ll;int dcmp(double x){if(fabs(x)<eps)return 0;return x>0?1:-1;}struct Point{double x,y;Point(double _x=0,double _y=0){x=_x;y=_y;}};Point operator + (Point a,Point b){return Point(a.x+b.x,a.y+b.y);}Point operator - (Point a,Point b){return Point(a.x-b.x,a.y-b.y);}double dist(Point a,Point b){double ss=a.x-b.x;double tt=a.y-b.y;return sqrt(ss*ss+tt*tt);}double Cross(Point a,Point b){return a.x*b.y-a.y*b.x;}int tot,id[40][40][40],state[11010];int getid(int a,int b,int c){if(b>c)swap(b,c);if(a>b)swap(a,b);if(b>c)swap(b,c);return id[a][b][c];}int head[11010],tol;struct Edge{int next,to;double val;}edge[2002000];void addedge(int u,int v,double val){edge[tol].to=v;edge[tol].val=val;edge[tol].next=head[u];head[u]=tol++;}double dp[11010][1<<6];int vis[10010][1<<6];Point p1[400],p2[400];int dd[500];double A[100100];bool check(Point a,Point b,Point c,Point d){double t1=fabs(Cross(a-d,b-d));double t2=fabs(Cross(a-d,c-d));double t3=fabs(Cross(b-d,c-d));double t4=fabs(Cross(b-a,c-a));if(dcmp(t4-t3-t2-t1)==0)return true;return false;}int main(){     //freopen("data.in","r",stdin);     //freopen("data.out","w",stdout);     int N,M,K; while(cin>>N>>M>>K){ memset(head,-1,sizeof(head));tol=0; tot=0; for(int i=1;i<=N;i++)cin>>p1[i].x>>p1[i].y; for(int i=1;i<=N;i++)cin>>dd[i],dd[i]--; for(int i=1;i<=M;i++)cin>>p2[i].x>>p2[i].y; for(int i=1;i<=M;i++) for(int j=i+1;j<=M;j++) for(int k=j+1;k<=M;k++) id[i][j][k]=++tot;// cout<<"tot="<<tot<<endl; memset(state,0,sizeof(state)); for(int i=1;i<=M;i++) for(int j=i+1;j<=M;j++) for(int k=j+1;k<=M;k++) for(int a=1;a<=N;a++) if(check(p2[i],p2[j],p2[k],p1[a]))state[id[i][j][k]]|=(1<<dd[a]); //cout<<"state: ";for(int i=1;i<=tot;i++)cout<<state[i]<<" ";cout<<endl; for(int i=1;i<=M;i++) for(int j=i+1;j<=M;j++) for(int k=j+1;k<=M;k++){ double val=dist(p2[i],p2[j])+dist(p2[i],p2[k])+dist(p2[j],p2[k]); addedge(0,id[i][j][k],0); A[id[i][j][k]]=val; } for(int i=1;i<=M;i++) for(int j=i+1;j<=M;j++) for(int k=j+1;k<=M;k++) for(int t=1;t<=M;t++){ if(t==i||t==j||t==k)continue; int s1=id[i][j][k],s2; double t1,t2; t1=Cross(p2[j]-p2[i],p2[k]-p2[i]);t2=Cross(p2[j]-p2[i],p2[t]-p2[i]);//i,j共边。 if(dcmp(t1)*dcmp(t2)<0)addedge(s1,getid(i,j,t),-2*dist(p2[i],p2[j])); t1=Cross(p2[k]-p2[i],p2[t]-p2[i]);t2=Cross(p2[k]-p2[i],p2[j]-p2[i]);//i,k共边 if(dcmp(t1)*dcmp(t2)<0)addedge(s1,getid(i,k,t),-2*dist(p2[i],p2[k])); t1=Cross(p2[k]-p2[j],p2[t]-p2[j]);t2=Cross(p2[k]-p2[j],p2[i]-p2[j]);//j,k共边 if(dcmp(t1)*dcmp(t2)<0)addedge(s1,getid(j,k,t),-2*dist(p2[j],p2[k])); } //cout<<"edge: "; for(int i=0;i<tol;i++)cout<<edge[i].val<<endl; for(int i=0;i<=tot;i++) for(int j=0;j<(1<<K);j++) dp[i][j]=INF; if(ans<INF)printf("%.12lf\n",ans); else puts("Impossible"); } //Point a,b,c,d;while(cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y)cout<<check(a,b,c,d)<<endl;     return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 浴缸下水器漏水怎么办 铁皮接头处漏水怎么办 马桶被堵死了怎么办 家里灯泡坏了怎么办 家里电路烧了怎么办 如果电脑开不了怎么办 热水器水管子漏水怎么办 淋浴头开关滴水怎么办 淋浴头一直滴水怎么办 饮水机放桶漏水怎么办 热水器热水阀门漏水怎么办 热水器热水出口漏水怎么办 热水器上水管漏水怎么办 水管往外漏水怎么办 ppr热水管漏水怎么办 大半夜水闸爆了怎么办 热水器不热水了怎么办 水龙头外皮裂了怎么办 电热水龙头坏了怎么办 太阳能存不住水怎么办 混水阀断裂漏水怎么办 洗澡淋浴头漏水怎么办 马桶有异物堵住怎么办 捷达机油盖漏油怎么办 乳化油臭了怎么办 自行车前叉严重生锈怎么办 自行车链条生锈了怎么办 自行车链子生锈了怎么办 对切削液过敏怎么办 齿轮油加到机油怎么办 机油加液压油里怎么办 液压油里面有水怎么办 加油站双层复合管漏油怎么办 预制屋面板底面渗漏怎么办 焊电焊眼睛疼怎么办 下水主管道篦子怎么办 墙里热水管堵了怎么办 热水管堵住了怎么办 热水管堵塞了怎么办 下水道被油渍堵死怎么办 赛欧车门打不开怎么办