当你打完部分分发现已经切了题
查看原帖
当你打完部分分发现已经切了题
195066
Loxilante楼主2023/11/6 22:10

6

开始部分分A(#13 #14)没打对交上去拿了95pts、WA了#14,直接整乐了。

合着无特殊性质的数据比有特殊性质的数据还要水?

改好部分分之后就A了。

#include <bits/stdc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
using namespace std;
const int U = 1e4;
double x[U], y[U];
bool vis[U];
double dp[(1<<18)+500][18];
int lst[(1<<18)+500][18];
double dis(int a, int b)
{
	return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
signed main(void)
{
	int n;
	cin>>n;
	rep(i, 0, n) cin>>x[i]>>y[i];

	bool B = 1;
	rep(i, 1, n)
	{
		if (x[i] <= x[i-1]) B = 0;
		if (y[i] >= y[i-1]) B = 0;
	}

	int k;
	double maxy = -1e100;
	rep(i, 0, n) if (y[i] > maxy) maxy = y[i], k = i;

	double ans = 0;
	if (B) rep(i, 0, n) cout<<i+1<<' ';
	else if (n <= 20)
	{
		rep(i, 0, 1<<n) rep(j, 0, 18) dp[i][j] = 1e100;
		dp[1<<k][k] = 0;

		rep(msk, 0, 1<<n)
		{
			rep(to, 0, n)
			{
				if ((msk>>to)&1) continue;
				rep(from, 0, n)
				{
					if (!((msk>>from)&1)) continue;
					if (dp[(1<<to)|msk][to] > dp[msk][from]+dis(from, to))
					{
						dp[(1<<to)|msk][to] = dp[msk][from]+dis(from, to);
						lst[(1<<to)|msk][to] = from;
					}
				}
			}
		}

		double minn = (double)1e100;
		int last;
		rep(i, 0, 18) if (minn > dp[(1<<n)-1][i]) minn = dp[(1<<n)-1][i], last = i;

		vector<int> v;
		v.pb(last);
		int msk = (1<<n)-1;
		rep(i, 0, n-2)
		{
			int l = lst[msk][last];
			v.pb(l);
			msk ^= 1<<last;
			last = l;
		}
		v.pb(k);
		reverse(v.begin(), v.end());

		rep(i, 0, n) cout<<v[i]+1<<' ';
	}
	else
	{
		vector<int> v1{k}, v2{k};
		vis[k] = 1;
		while(v1.size() < n)
		{
			double mindis = 1e100;
			int lst = v1.back(), t;
			rev(i, n-1, 0) if (!vis[i] && mindis-dis(lst, i) > 1e-7) mindis = dis(lst, i), t = i;
			v1.pb(t);
			vis[t] = 1;
		}

		ms(vis, 0);
		vis[k] = 1;
		while(v2.size() < n)
		{
			double mindis = 1e100;
			int lst = v2.back(), t;
			rep(i, 0, n) if (!vis[i] && mindis-dis(lst, i) > 1e-7) mindis = dis(lst, i), t = i;
			v2.pb(t);
			vis[t] = 1;
		}

		double ans1 = 0, ans2 = 0;
		rep(i, 1, n)
		{
			ans1 += dis(v1[i], v1[i-1]);
			ans2 += dis(v2[i], v2[i-1]);
		}

		if (ans1 > ans2) rep(i, 0, n) cout<<v2[i]+1<<' ';
		else rep(i, 0, n) cout<<v1[i]+1<<' ';
	}

	return 0;
}
2023/11/6 22:10
加载中...