校赛热身 Problem C. Sometimes Naive (状压dp)

  1. 题解:  
  2. 列举每一种3的倍数的组合,开始先求出3条边的可行解,则  
  3. 六条边的可行解可以由两个三条边得来。 
  4. 详见代码解析
#include<bits/stdc++.h>  
using namespace std;  
int a[22],n,cnt,ant,is[500007],dp[1050007];  
struct node  
{  
    int num,id;  
}angle[500007];  
bool cmp(const node& a,const node& b)  
{  
    return a.num<b.num;  
}  
int abs1(int x)  
{  
    if(x<0)return -x;  
    return x;  
}  
void init()  
{  
    for(int i=0;i<(1<<n);i++)  
    {  
        int ans=0,t=i;  
        while(t)  
        {  
            if(t&1)ans++; //这一位是1节++
            t=t>>1;  //右移
        }  
        if(ans%3==0)  
        {  
            angle[cnt].id=i;  
            angle[cnt++].num=ans/3;  
        }  
        if(ans==3)  
        {  
            int v[4],ans1=0,ans2=0,t=i;  
            while(t)  
            { //把二进制位是1的边对应上 
                if(t&1)v[ans1++]=a[ans2];  
                t=t>>1;  
                ans2++;  
            }  
            if(abs1(v[1]-v[2])<v[0]&&abs1(v[1]-v[0])<v[2]&&abs1(v[2]-v[0])<v[1])  
            {  //两边只差小于第三边,和会超int
                is[ant++]=i;  
                dp[i]=1;
            }  
        }  
    }  
}  
int main()  
{  
    int T,cas=0;scanf("%d",&T);  
    while(T--)  
    {  
        scanf("%d",&n);  
        for(int i=0;i<n;i++)  
            scanf("%d",&a[i]);  
        cnt=0,ant=0;  
        memset(dp,0,sizeof(dp));  
        dp[0]=1;  
        init();  
        sort(angle,angle+cnt,cmp);//要排序 
        for(int i=0;i<cnt;i++)  
        {  
            node e=angle[i];  
            for(int j=0;j<ant;j++)  
            {  
                //&位运算
                if(dp[e.id]&&!(e.id&is[j]))//若e.id已存在并且  
                //.e.id中的边与is[j]中没有重边则dp[e.id|is[j]]=1  
                    dp[e.id|is[j]]=1;//推到下一个  
            }  
        }  
        for(int i=cnt-1;i>=0;i--)  
        {  
            if(dp[angle[i].id])  //答案要最多,从后往前遍历
            {  
                printf("Case #%d: %d
",++cas,angle[i].num);  
                break;  
            }  
        }  
    }   
    return 0;  
}
原文地址:https://www.cnblogs.com/caiyishuai/p/13271111.html