ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

8C - Looking for Order 状压DP

2021-04-06 02:05:26  阅读:220  来源: 互联网

标签:dist struct int 8C 状压 Looking continue 物品 com


原题链接https://codeforces.com/problemset/problem/8/C

这题自己写状压是没问题,但是细节没把握好,wa了,然后参考了大佬的博客.
据说这题还可以暴搜实现,懒得想了(说不定剪枝啥的不好想)。

题意:
一个女孩整理箱子,箱子的位置不可以改变,告诉你箱子和每个行李的位置,她一次可以拿两个或者是一个行李,女孩移动时间花费是她移动距离的平方,求最小花费时间和移动方案。

思路: 以下思路来自https://www.luogu.com.cn/blog/hxy1117/solution-cf8c
拿到题, \(n<=24n<=24\) 的数据范围和512MB的空间限制基本上就标志着这道题是一个标准的状压。为了节省空间,我们就 \(1<<i-1\) 表示第 \(i\) 个物品有无被取过。由于一次可以选择拿一个或者两个物品,考虑在状态转移的时候枚举这次拿的两个物品(如果两个物品相同就处理为这次只拿一个)。由于要输出拿的方法,我们就再用一个数组记录当前状态是从之前的哪个状态转移过来的即可。
需要注意的是,可以证明,若设每次离开手提包捡拾物品为一次,则各次之间的顺序不影响最终答案。如,第一次拿物品1,第二次拿物品2,3与第一次拿物品2,3,第二次拿物品1的所用时间是一样的。这样,我们在转移的时候就从编号小的物品向编号大的物品找寻,只要找到了当前的一种可用方案就可以进入下一个状态了,这样可以节省时间(同时避免重复计算)。

代码如下

int a, b, n;
struct point{
	int x, y;
}p[N];
struct node{
	int x, y, z;
};
int dist[N][N];
int f[1 << 24];
node pre[1 << 24];

int get(int p1, int p2)
{
	int x = p[p1].x - p[p2].x;
	int y = p[p1].y - p[p2].y;
	return x * x + y * y;
}

int main()
{
	IOS;
	cin >> a >> b >> n;
	p[0].x = a, p[0].y = b;
	for(int i = 1 ; i <= n ; i ++)
		cin >> p[i].x >> p[i].y;
	for(int i = 0 ; i <= n ; i ++)
		for(int j = 0 ; j <= n ; j ++)
			dist[i][j] = get(i, j);
	
	memset(f, 0x3f, sizeof f);
	f[0] = 0;
	for(int k = 0 ; k < (1 << n) ; k ++)
	{
		for(int i = 0 ; i < n ; i ++)		//物品按照编号递增枚举 
		{
			if((k >> i) & 1) continue;		//如果当前物品 1 已经被拿过了 
			for(int j = 0 ; j < n ; j ++)
			{
				if((k >> j) & 1) continue; //如果当前物品 2 已经被拿过了 
				if(f[k | (1 << i) | (1 << j)] > f[k] + dist[0][i + 1] + dist[i + 1][j + 1] + dist[j + 1][0])
				{
					f[k | (1 << i) | (1 << j)] = f[k] + dist[0][i + 1] + dist[i + 1][j + 1] + dist[j + 1][0];
					pre[k | (1 << i) | (1 << j)] = {k, i + 1, j + 1};
				}
			}
			break;	//由于答案和顺序无关
			// 因此我们只要能把物品 1 放进去,就可break		
		}

	}
	
	cout << f[(1 << n) - 1] << endl;
	vector<int> ans;
	auto t = pre[(1 << n) - 1];
	while(1)
	{
		ans.push_back(0);
		ans.push_back(t.y);
		if(t.y != t.z)
			ans.push_back(t.z);
		if(t.x == 0) break;
		t = pre[t.x];
	}
	ans.push_back(0);
	for(int i = ans.size() - 1 ; i >= 0 ; i --)	cout << ans[i] << " ";
	cout << endl;
	
	return 0;
}

标签:dist,struct,int,8C,状压,Looking,continue,物品,com
来源: https://www.cnblogs.com/luoyicong/p/14620059.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有