HDU 3920Clear All of Them I(状压DP)

本文解析HDU3920题目,采用状态压缩动态规划解决炮弹打击敌人的最优化问题。通过优化算法降低复杂度,确保算法效率。

HDU 3920   Clear All of Them I

题目是说有2n个敌人,现在可以发n枚炮弹,每枚炮弹可以(可以且仅可以)打两个敌人,每一枚炮弹的花费等于它所行进的距离,现在要消灭所有的敌人,问最少花费是多少(反正题意大概就是这样啦,知道怎么回事就好了,解释不清了)

一看到n<=10而且又是在DP专题里的,就知道这个显然是状压DP,由于有2n个敌人,所以状态表示由当前状态再打两个人来转移,

10000100表示打了这两个敌人的最小花费

所以状态的转移是由前往后递推的,假如当前状态是cur,上一个状态是last,应该满足存在i!=j有last&(1<<i)=0且last&(1<<j)=0且last | (1<<i)|(1<<j) = cur,由此来更新当前的状态cur,最后的答案就是DP[(1<<(2n)) - 1]

注意到上面我们是要枚举i和j的,所以这个的总复杂度就是20 * 20 * 2^20,这显然是会超时的, 所以需要优化

注意到如果存在两队人(a,b)(c,d)我们先打(a, b)再打(c, d)和先打(c,d)在打(a, b)是一样的,所以我们完全可以每次取last中最小的一位是0的与后面所有的0组合,这样不仅没有漏掉解,而且复杂度也将到了O(20 * 2^20)这就可以过了

下面从前往后美剧上一个状态时递推时我是用的队列存的所有状态,其实枚举过去也是可以的

  1 //#pragma comment(linker,"/STACK:102400000,102400000")
  2 #include <map>
  3 #include <set>
  4 #include <stack>
  5 #include <queue>
  6 #include <cmath>
  7 #include <ctime>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cctype>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <iostream>
 14 #include <algorithm>
 15 using namespace std;
 16 #define INF 1e9
 17 #define inf (-((LL)1<<40))
 18 #define lson k<<1, L, mid
 19 #define rson k<<1|1, mid+1, R
 20 #define mem0(a) memset(a,0,sizeof(a))
 21 #define mem1(a) memset(a,-1,sizeof(a))
 22 #define mem(a, b) memset(a, b, sizeof(a))
 23 #define FOPENIN(IN) freopen(IN, "r", stdin)
 24 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
 25 template<class T> T CMP_MIN(T a, T b) { return a < b; }
 26 template<class T> T CMP_MAX(T a, T b) { return a > b; }
 27 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 28 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 29 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 30 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 31 
 32 //typedef __int64 LL;
 33 //typedef long long LL;
 34 const int MAXN = 105;
 35 const int MAXM = 100005;
 36 const double eps = 1e-13;
 37 //const LL MOD = 1000000007;
 38 
 39 int T, N;
 40 typedef double Point[2];
 41 Point st, p[MAXN];
 42 double dis[MAXN][MAXN], d[MAXN], dp[1<<21];
 43 
 44 double calc(Point a, Point b)
 45 {
 46     double x = a[0] - b[0];
 47     double y = a[1] - b[1];
 48     return sqrt(x*x + y*y);
 49 }
 50 
 51 void getDis()
 52 {
 53     for(int i=0;i<N;i++)
 54     {
 55         d[i] = calc(st, p[i]);
 56         for(int j=i+1;j<N;j++)
 57         {
 58             dis[j][i] = dis[i][j] = calc(p[i], p[j]);
 59         }
 60     }
 61 }
 62 
 63 int main()
 64 {
 65     int t = 0;
 66     scanf("%d", &T);
 67     while(T--)
 68     {
 69         scanf("%lf %lf", &st[0], &st[1]);
 70         scanf("%d", &N);
 71         N <<= 1;
 72         for(int i=0;i<N;i++)
 73             scanf("%lf %lf", &p[i][0], &p[i][1]);
 74         getDis();
 75         dp[0] = 0;
 76         for(int i=1;i<(1<<N);i++) dp[i] = INF;
 77         queue<int>q;
 78         q.push(0);
 79         while(!q.empty())
 80         {
 81             int now = q.front(); q.pop();
 82             int f=0, r;
 83             while( now & (1<<f)  && f < N)
 84                 f++;
 85             for(r = f + 1; r < N; r ++ )
 86                 if(!(now & (1<<r)))
 87             {
 88                 int next = now | (1<<f) | (1<<r);
 89                 double minDis = MIN(d[f], d[r]) + dis[f][r];
 90                 if( fabs(dp[next] - INF) < eps )
 91                 {
 92                     q.push(next);
 93                     dp[next] = dp[now] + minDis;
 94                 }
 95                 else if( dp[now] + minDis < dp[next] )
 96                     dp[next] = dp[now] + minDis;
 97             }
 98         }
 99         printf("Case #%d: %.2lf%\n", ++t, dp[(1<<N)-1]);
100     }
101     return 0;
102 }

 

转载于:https://www.cnblogs.com/gj-Acit/p/3888286.html

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值