• # 交换茸角 状态DP 思路清奇


    交换茸角 状态DP 思路清奇


    问题:
    动物园里有 $n $头麋鹿。每头麋鹿有两支茸角,每支茸角有一个重量。

    然而,一旦某头麋鹿上两支茸角的重量之差过大,这头麋鹿就会失去平衡摔倒。为了不然这种悲剧发生,动物园院长决定交换某些茸角,使得任意一头麋鹿的两角重量差不超过$ c$。
    然而,交换两支茸角十分麻烦,不仅因为茸角需要多个人来搬运,而且会给麋鹿造成痛苦。因此,你需要计算出最少交换次数,使得任意一头麋鹿的两角重量差不超过 (c)

    注意,交换两支茸角只能在两头麋鹿之间进行。因为交换同一头麋鹿的两支角是没有意义的。


    解:
    这道题思路真的不容易想到
    首先我想了半天 发现普通的状态无法推导

    然后我看了一眼题解 还是 感觉 思路真的难想到

    首先 我们应该先抛开 最小交换的条件 而去考虑不满足条件的因素
    我们贪心一下
    显然就是 排完序后 两两 之差 (>c)
    满足条件的情况 就是 两两之差 (<=c)

    然后我们考虑 状态压缩 首先我们先设 f[i]为 集合i 里面都满足条件的最小步数

    • 对于集合里面不满足条件的 显然是 inf
    • 对于集合里面满足条件的 是0
    • 而 满足条件但是原来不满足的 设为集合个数 sum-1

    (f[i]=min(f[j]+)(f[i)^(j]));

    考虑区间合并

    这道题另一个思路清奇的地方
    为什么这么做是对的,所以 我们可以对于那些需要全部交换的,答案就是sum-1
    而对那些有的不需要交换的 可以通过子集递推

    code:

    //
    #include<bits/stdc++.h>
    using namespace std;
    #define maxnn 1000000
    int n;
    int a1[maxnn],a2[maxnn];
    int tmp[maxnn];
    int tot=0;
    int f[maxnn];
    int all=0;
    #define inf 10000000
    int c;
    int main()
    {
    	cin>>n>>c;
    	all=(1<<n)-1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a1[i]);
    		scanf("%d",&a2[i]);
    	}
    	for(int s=0;s<=all;s++)
    	{
    		tot=0;
    		int ty=0;
    		int fla1=1;
    		for(int i=1;i<=n;i++)
    		{
    			if(s&(1<<i-1))
    			{
    				ty++;
    				tmp[++tot]=a1[i];
    				tmp[++tot]=a2[i];
    				if(abs(a1[i]-a2[i])>c) fla1=0;
    			}
    		}
    		sort(tmp+1,tmp+1+tot);
    		int fla=1;
    		for(int i=tot;i>=2;i-=2)
    		{
    			if(tmp[i]-tmp[i-1]>c)
    			{
    				fla=0;
    			}
    		}
    		if(fla==0) f[s]=inf;
    		else 
    		if(fla1==1) f[s]=0;
    		else
    		f[s]=ty-1;
    	}
    	for(int s=0;s<=all;s++)
    	{
    		for(int i=s;i;i=(i-1)&s)
    		{
    			int k=s^i;
    			f[s]=min(f[s],f[i]+f[k]);
    		}
    	}
    	if(f[all]!=inf) cout<<f[all];
    	else cout<<-1;
    	
    	
    	
    }
    
    
    刀剑映出了战士的心。而我的心,漆黑且残破
  • 相关阅读:
    设计模式-策略模式
    设计模式-建造者模式
    js助手函数
    Javascript使用函数做命名空间
    腾讯云scf云函数,python依赖安装与上传的正确姿势
    nodejs爬虫,服务器经常返回ECONNRESET或者socket hang up错误的解决方法
    http请求,服务器回复内容为乱码的一种可能解决方法
    js在动态定义的新对象中,属性为变量时,如何动态定义
    nodejs中使用request时出现unable to verify the first certificate的一种解决办法
    Ubuntu偶然出现在待机解锁时,密码输入肯定正确但却无法进入的一种可能性
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11454743.html
Copyright © 2020-2023  润新知