dfs剪枝可过,tle并非数据强度过大
  • 板块P1433 吃奶酪
  • 楼主JackcreaM
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/12/14 21:02
  • 上次更新2023/12/15 00:04:53
查看原帖
dfs剪枝可过,tle并非数据强度过大
54465
JackcreaM楼主2023/12/14 21:02

hack数据组的第一个数据有重复点,简单的解决方法是去重。照搬离散化处理的前置操作(笑

#include<bits/stdc++.h>
using namespace std;
int n;
double l[100][100];//存两点之间的距离
double a[100][2];
double hist[(1 << 15) + 5][16];//在已经走过一些点时走到某个点的路程最小值
double ans=INT_MAX;
double length(double a1, double b1, double a2, double b2)
{
	//cout << a1 - a2 << " " << b1 - b2 << endl;
	return sqrt((a1 - a2) * (a1 - a2) + (b1 - b2) * (b1 - b2));
}
bool done[100];//标记这个点是否走过
//x表示当前走了多少个点 p表示当前位置的二进制序号 ansnow表示当前的总路程 i表示当前点的序号
void dfs(int x,int p,double ansnow,int i)
{
	if (x >= n + 1)//已经走完了
	{
		if (ansnow < ans)
			ans = ansnow;
		return;
	}
	for(int j=1;j<=n;j++)
		if (!done[j])//如果这个点没被走过
		{
			int newp = p + (1 << (j - 1));//p+2*n^(j-1),显然同一个p值只能是一种走法
			double newans = ansnow + l[j][i];
			if (hist[newp][j])//首先这个点要被走过
				if (hist[newp][j] < newans)//而且有更短的走法
					continue;//剪枝
			done[j] = true;
			hist[newp][j] = newans;
			dfs(x + 1, newp, newans, j);
			done[j] = false;//回溯
		}
}
int main()
{
	cin >> n;
	int i, j;
	a[0][0] = 0;
	a[0][1] = 0;//起点


	vector<pair<double, double>>A;//去重的部分:有一个点有重复数据
	for (i = 1;i <= n;i++)
	{
		double x, y;
		cin >> x >> y;
		A.push_back(pair<double, double>(x, y));
	}
	sort(A.begin(), A.end());
	A.erase(unique(A.begin(), A.end()), A.end());
	n = A.size();


	for (i = 0;i < n;i++)
	{
		a[i + 1][0] = A[i].first;
		a[i + 1][1] = A[i].second;
	}
	for (i = 0;i <= n;i++)
	{
		for (j = i + 1;j <= n;j++)
		{
			double x = length(a[i][0], a[i][1], a[j][0], a[j][1]);
			l[i][j] = x;
			l[j][i] = x;
			//cout << x << endl;
		}
	}
	dfs(1, 0, 0, 0);
	cout << fixed << setprecision(2) << ans << endl;
	return 0;
}
2023/12/14 21:02
加载中...