BNU 22494 Kitchen Robot
2015-09-09 18:30
176 查看
【题目链接】http://www.bnuoj.com/v3/problem_show.php?pid=22494
【解题报告】
【参考代码】
【解题报告】
平面上n个点,求把它们全部收集起来的最小距离。首先看到1<=n<=18可以想到进行状态压缩,使用二进制值来保存收集状态,于是这道题目可以明确使用状态压缩dp来解决。 设dp[S][v]表示在点集S中v是最后一个被收集的点,那么它可以由以下状态转移而来: dp[S^(1<<i)][i]+dis[i][v]( 1<=i<=n,i!=v ) 我们需要在这些状态中选择最小的方案来对dp[S][v]进行更新。于是可以对n个点跑一遍dfs( (1<<n)-1,i ) (1<=i<=n),于是得到以这i个点为最后一个收集点的n种方案,加上处理掉最后一个点的花费enddis[i],即全集为S的n种最优方案,在这里面选择最小的那个即为最终结果。细节部分请参阅代码。
【参考代码】
//状态压缩跑一遍dfs #include<cstdio> #include<iostream> #include<stack> #include<algorithm> #include<cmath> #include<cstring> using namespace std; double INF=2*1e9+1e8; struct point{ double x,y; }robot[20]; int w,l,n; double x0,y0; double dis[20][20],enddis[20],dp[1<<21][20]; double dis0[20]; double getdis( double x1, double y1, double x2, double y2 ) { return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) ); } void get_enddis( int i ) { double temp=robot[i].x; temp=min( temp, robot[i].y ); temp=min( temp, w-robot[i].x ); temp=min( temp, l-robot[i].y ); enddis[i]=temp; } void init() { for(int i=0;i<=(1<<n);i++)for(int j=0;j<=n;j++)dp[i][j]=INF; //dp值初始化范围小了 for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)dis[i][j]=INF; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { dis[i][j]=getdis( robot[i].x,-robot[i].y, robot[j].x,robot[j].y ); dis[i][j]=min( dis[i][j], getdis( -robot[i].x,robot[i].y, robot[j].x,robot[j].y ) ); dis[i][j]=min( dis[i][j], getdis( robot[i].x,robot[i].y, robot[j].x,2*l-robot[j].y ) ); dis[i][j]=min( dis[i][j], getdis( robot[i].x,robot[i].y, 2*w-robot[j].x,robot[j].y ) ); dis[j][i]=dis[i][j]; } for(int j=0;j<n;j++) dis0[j]=getdis( x0,y0, robot[j].x,robot[j].y ); for(int i=0;i<n;i++)get_enddis(i); } double dfs( int S, int v ) { //cout<<"S="<<S<<endl; if( S==(1<<v) )return dp[(1<<v)][v]=dis0[v]; //一开始更新成了dp[0][v]所以... if( dp[S][v]!=INF )return dp[S][v]; for( int i=0;i<n;i++ )if( i!=v && ((1<<i)&S) ) { dp[S][v]=min( dp[S][v], dfs( S^(1<<v) ,i )+dis[i][v] ); } return dp[S][v]; } int main() { int T; cin>>T; while(T--) { scanf("%d%d%d",&w,&l,&n); for(int i=0;i<n;i++)scanf("%lf%lf",&robot[i].x,&robot[i].y); scanf("%lf%lf",&x0,&y0); init(); double ans=INF; for(int i=0;i<n;i++) //dis和enddis都求错了所以...... { double temp=dfs( (1<<n)-1, i ); temp+=enddis[i]; ans=min( ans,temp ); } printf("%.6f\n",ans); } return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow
- zoj3605 Find the Marble(三维dp)
- Word Break I,II, Triangle,Palindrome Partitioning 动态规划 DP