• HDU2489【状压枚举】


    题意:

    给你n个点的图,然后让你在图里挑m个点,达到sumedge/sumnode最小

    思路:

    由于数据范围小,状压枚举符合m个点的状态,我是用vactor存了结点位置,也记录了结点的sum值,然后跑一发最小生成树就可以知道sumedge,这里判断可以利用乘法,然后更新一个状态就好了;

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    int ma[20][20];
    int val[20];
    int sumnode,sumedge;
    int n,m;
    int cnt;
    int a,b;
    int dis[20];
    vector<int>pb;
    bool vis[20];
    
    int prim()
    {
        memset(vis,0,sizeof(vis));
        dis[pb[0]]=0;
        vis[pb[0]]=1;
        for(int i=1;i<pb.size();i++)
        {
            dis[pb[i]]=ma[pb[0]][pb[i]]?ma[pb[0]][pb[i]]:1000000;
        }
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            int k=-1;
            int mimi=1000000;
            for(int j=0;j<pb.size();j++)
            {
                if(vis[pb[j]]) continue;
                if(dis[pb[j]]<mimi)
                {
                    mimi=dis[pb[j]];
                    k=j;
                }
            }
            if(k==-1)
                break;
            vis[pb[k]]=1;
            for(int j=0;j<pb.size();j++)
            {
                if(ma[pb[k]][pb[j]]&&!vis[pb[j]]&&dis[pb[j]]>ma[pb[k]][pb[j]])
                    dis[pb[j]]=ma[pb[k]][pb[j]];
            }
        }
        for(int i=0;i<pb.size();i++)
        {
            ans+=dis[pb[i]];
        }
        return ans;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m))
        {
            if(!n&&!m) break;
    
            for(int i=0;i<n;i++)
                scanf("%d",&val[i]);
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                {
                    scanf("%d",&ma[i][j]);
                    if(ma[i][j]==0)
                        ma[i][j]=1000000;
                }
            a=1000000;
            b=1;
            int build=1<<n;
            int ans;
            for(int i=0;i<=build;i++)
            {
                int cnt=0;
                sumnode=0;
                pb.clear();
                for(int j=0;j<n;j++)
                {
                    if(i&(1<<j))
                    {
                        cnt++;
                        pb.push_back(j);
                        sumnode+=val[j];
                    }
                }
                if(cnt==m)
                {
                    int sumedge=prim();
                    if(a*sumnode>sumedge*b)
                    {
                        a=sumedge;
                        b=sumnode;
                        ans=i;
                    }
                }
            }
            int flag=0;
            for(int i=0;i<n;i++)
            {
                if(ans&(1<<i))
                {
                    if(flag) printf(" ");
                    printf("%d",i+1);
                    flag=1;
                }
            }
            puts("");
        }
        return 0;
    
    }


  • 相关阅读:
    书单
    x&(x1)表达式的意义
    约瑟夫环,杀人游戏(静态循环链表实现)
    我的第一个动态规划程序(试图用递归求斐波拉契数)
    NYOJ 2题 括号配对问题
    为什么 C++不叫作++C? o(∩_∩)o
    文字常量区,字符串常量
    括号匹配(栈实现)
    Mybatis的逆向工程(generator)
    Mybatis学习一(介绍/举例/优化)
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6216816.html
Copyright © 2020-2023  润新知