Topcoder SRM 718 Hard

链接:https://community.topcoder.com/stat?c=problem_statement&pm=14607&rd=16933

题意:给一个排列p[n],定义f(k)表示它长度为k的所有子序列提取出来,对于每一个按大小顺序标号之后形成的本质不同的排列个数是否为C(n, k),现在你要补全一个排列,使∑f(k)最大,然后字典序最小

题解:考虑f(n - 1) = 1的时候,我们注意到只要相邻两个之差不为1就行了

然后f(n - k) = 1的时候,归纳一下就可以发现只要min(|i - j| + |p[i] - p[j]|) >= k就可以了

证明挺简单的

然后就直接搜就好了

#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;

typedef long long LL;
typedef pair < int, int > pii;

class PermutationSubsequence
{
	public:
		inline bool Dfs(vector < int > &cur, vector < int > &p, int x, int n, int v, int S)
		{
			if (x == n)
				return true;
			if (~p[x])
			{
				for (int i = 0; i < x; i ++)
					if (x - i + abs(p[x] - cur[i]) < v)
						return false;
				cur[x] = p[x];
				if (Dfs(cur, p, x + 1, n, v, S))
					return true;
			}
			for (int i = 0; i < n; i ++)
				if (S >> i & 1)
				{
					bool f = 1;
					for (int j = 0; j < x; j ++)
						if (x - j + abs(i - cur[j]) < v)
							f = 0;
					if (f)
					{
						cur[x] = i;
						if (Dfs(cur, p, x + 1, n, v, S ^ 1 << i))
							return true;
					}
				}
			return false;
		}

		vector < int > findBest(vector < int > arr)
		{
			int n = arr.size(), S = (1 << n) - 1;
			vector < int > ans(n);
			for (int i = 0; i < n; i ++)
				if (~arr[i])
					S ^= 1 << arr[i];
			for (int i = n; i; i --)
				if (Dfs(ans, arr, 0, n, i, S))
					return ans;
		}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值