zoukankan      html  css  js  c++  java
  • 校赛热身 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;  
    }
  • 相关阅读:
    284. Peeking Iterator
    283. Move Zeroes
    282. Expression Add Operators
    281. Zigzag Iterator
    280. Wiggle Sort
    279. Perfect Squares
    python 正则匹配替换,在匹配的字符后方添加新的字符
    odoo default_get 方法和onchange装饰器造成冲突,
    redmine 如何启用用户图标
    odoo 打印执行的sql语句
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/8594864.html
Copyright © 2011-2022 走看看