zoukankan      html  css  js  c++  java
  • bzoj3900: 交换茸角

    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]);
    }
  • 相关阅读:
    01-面向对象
    12-期末作业
    11-Linux-vim /bash
    组播地址
    rip
    华为hcnp r&s考试一共有三门,R&S-IERS,R&S-IENP,R&S-IEEP

    spring注解开发
    yml和properties的加载顺序和区别
    @ImportResource
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8454645.html
Copyright © 2011-2022 走看看