牛客多校3 - Two Matchings(dp)

题目链接:点击查看

题目大意:给出 n 个点( n 为偶数 ),题目需要求出两个完全没有交集的匹配 q 和 p ,一方面使得 n 个点两两互相匹配,另一方面使得匹配的权值和最小

题目分析:一道 dp 题,比赛时贪心WA了一下午,就比较自闭了

因为 n 是偶数,所以可以考虑将 n 个数分配到不同的长度为偶数的环中,对于排列 q 和排列 p,只需要在偶环中交换一下位置就好了

但这个偶环的长度必须要大于 2 ,因为如果长度为 2 的话,那么无法保证两个匹配 q 和 p 不存在交集

还有一个需要观察或者猜出的结论就是,任意长度大于等于 8 的偶环,都可以分解为长度为 4 和长度为 6 的偶环,且总边权更小

那么现在就对于长度为 4 和长度为 6 的偶环计算一下贪心可以获得的最小边权之和是多少吧,直接上图:

 

这样总结一下,对于长度为 x 的偶环( x = 4 或 x = 6 ),贪心可以得到的最小权值和为 2 * ( a[ i ] - a[ i - x ] ) ,注意 a 数组是排序后的数组

这样我们直接进行动态规划就好了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
  
typedef long long LL;
  
typedef unsigned long long ull;
  
const int inf=0x3f3f3f3f;
  
const int N=2e5+100;

int a[N];

LL dp[N];
  
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int w;
	cin>>w;
	while(w--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d",a+i);
		sort(a+1,a+1+n);
		dp[0]=0;
		dp[2]=inf;
		dp[4]=a[4]-a[1];
		for(int i=6;i<=n;i+=2)
			dp[i]=min(dp[i-4]+a[i]-a[i-3],dp[i-6]+a[i]-a[i-5]);
		printf("%lld\n",2*dp[n]);
	}






















    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/107455334