码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj千题计划240:bzoj3900: 交换茸角

时间:2018-02-19 23:46:53      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:int   ems   font   algo   line   计划   初始化   ref   cst   

http://www.lydsy.com/JudgeOnline/problem.php?id=3900

 

dp[i]表示让状态为i的鹿满足要求的最少交换次数

不能枚举两头鹿交换,因为一头鹿可能交换多次后转移到下一个状态

那就枚举子集 dp[i]=min { dp[j]+dp[j^i] }

初始化:将i这个状态上的麋鹿的角从小到大排序后,若相邻的i和i+1满足 h[i+1]-h[i]<=c,则dp[i]=鹿的个数-1,否则dp[i]=inf

因为若有t只鹿,在确保一定能通过交换满足要求的情况下,直接把它需要的那个换过来即可

 

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int a[17],b[17]; 

int dp[1<<16];

int tmp[33];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d%d",&a[i],&b[i]);
    memset(dp,63,sizeof(dp));
    int S=1<<n;
    int tot; bool tag;
    for(int i=1;i<S;++i)
    {
         tot=0;
         tag=false;
         for(int j=1;j<=n;++j)
             if(i&(1<<j-1)) 
            {
                 if(abs(a[j]-b[j])>m) tag=true;
                 tmp[++tot]=a[j],tmp[++tot]=b[j];
            }
         if(!tag) { dp[i]=0; continue; }
         sort(tmp+1,tmp+tot+1);
         for(int j=1;j<=tot;j+=2)
             if(tmp[j+1]-tmp[j]>m) { tag=false; break; }
         if(tag) dp[i]=tot/2-1;
    }
    for(int s=1;s<S;++s)
        for(int t=(s-1)&s;t;t=(t-1)&s)
            dp[s]=min(dp[s],dp[t]+dp[s^t]);
    if(dp[S-1]>=n) printf("-1");
    else printf("%d",dp[S-1]);
}

 

bzoj千题计划240:bzoj3900: 交换茸角

标签:int   ems   font   algo   line   计划   初始化   ref   cst   

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8454645.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!