HDU3920 状压DP+优化+记忆化搜索

来源:互联网 发布:程序员一个月工资 编辑:程序博客网 时间:2024/05/16 07:47

先按每个点到射击点的距离排个序,然后记忆化搜索,用状态压缩dp即可

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int MAXN = 21;#define EPS 1e-8int n;struct Point{double x,y;Point(){}Point(double _x,double _y):x(_x),y(_y){}void input(){scanf("%lf%lf",&x,&y);}}ps[MAXN];Point o;double dp[1<<MAXN];double dis[MAXN][MAXN];double odis[MAXN];int MAXS;inline double pdis(Point a,Point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}inline int cmp(Point a,Point b){return pdis(o,a) < pdis(o,b);}inline double dfs(int u){if(dp[u] > EPS)return dp[u];if(u == 0)return 0.0;int y = 0;while (!(u&(1<<y)))y ++;int tmp;for(int i = y+1; i < n; ++i){if(u&(1<<i)){tmp = u - (1<<i) - (1<<y);double temp = dfs(tmp) + odis[y] + dis[y][i];if(dp[u] < -EPS || dp[u] > temp)dp[u] = temp;}}return dp[u] < -EPS ? 0.0 : dp[u];}int main(){int cas;scanf("%d",&cas);for(int kcas = 1; kcas <= cas; ++kcas){o.input();scanf("%d",&n);for(int i = 0; i < 2*n; ++i)ps[i].input();sort(ps,ps+2*n,cmp);n = 2*n;for(int i = 0; i < n; ++i)for(int j = 0; j < n; ++j){dis[i][j] = pdis(ps[i],ps[j]);}for(int i = 0; i < n; ++i){odis[i] = pdis(o,ps[i]);}MAXS = 1<<n;for(int i = 0; i < MAXS; ++i)dp[i] = -1.0;dfs(MAXS-1);printf("Case #%d: ",kcas);printf("%.2lf\n",dp[MAXS-1]);}}



原创粉丝点击