zoukankan      html  css  js  c++  java
  • POJ--2288--Islands and Bridges(状态压缩DP+bfs)

    介绍

    通过图G经过所有的节点,且所有的节点仅经过一次的通路,就是哈密顿通路。

    题意

    有N座岛,M座桥,让你找到一条哈密顿通路,当经过一座岛就加上该岛的价值,如果相邻两岛之间有桥再加上两岛价值之积,如果相邻三岛之间两两都有桥,再加上三岛价值之积。求最大总价值是多少以及达到最大总价值的路径有几条。

    思路
    这道题还算一个比较中规中矩的状压DP入门题。就是得设计两个状态转移方程,所以有写麻烦。

    两个状态转移方程都是代表在这次选了j节点上次选了k节点而达到了 i+sta[j] 状态。dp_v 用来存该情况下最大总价值,dp_n用来存达到同种情况下的达到最大总价值的方案数。

    dp_v[i+sta[j]][j][k]=max(dp_v[i][k][z]+V(经过这个点所带的总价值));

    dp_n[i+sta[j]][j][k]+=dp[i][k][z];

    注意:N==1时;用__int64保存;T组数据;方案数除以2。

    代码如下:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<string.h>
    #include<queue>
    using namespace std;
    int sta[15]= {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};
    __int64 dp_n[1<<13][13][13];
    __int64 dp_v[1<<13][13][13];
    bool flag[1<<13][13][13];//入队列时进行标记,否则会造成重复入队列,会超内存
    int N,M,val[15],g[15][15];
    __int64  ans_1,ans_2;
    struct node
    {
        short i,j,k;
    };
    
    void init()//初始化
    {
        memset(g,0,sizeof(g));
        memset(dp_n,0,sizeof(dp_n));
        memset(dp_v,-1,sizeof(dp_v));
        memset(flag,0,sizeof(flag));
    }
    queue<node>q;
    void solve()
    {
        node temp;
        for(int i=0; i<N; ++i)
        {
            temp.i=sta[i];
            temp.j=i;
            temp.k=i;
            flag[temp.i][temp.j][temp.k]=1;
            dp_n[temp.i][temp.j][temp.k]=1;
            dp_v[temp.i][temp.j][temp.k]=val[i];
            q.push(temp);
    
        }
        while(!q.empty())
        {
            int i=q.front().i;
            int j=q.front().j;
            int k=q.front().k;
            flag[i][j][k]=0;
            q.pop();
            for(int z=0; z<N; ++z)
            {
                if(g[j][z]&&((i&sta[z])==0))
                {
                    temp.i=i+sta[z];
                    temp.j=z;
                    temp.k=j;
                    __int64 temp_v;
                    temp_v=dp_v[i][j][k]+val[z]+val[z]*val[j];
                    if(g[z][k]&&k!=j)
                            temp_v+=val[z]*val[j]*val[k];
                    if(dp_v[temp.i][temp.j][temp.k]==temp_v)
                    {
                        dp_n[temp.i][temp.j][temp.k]+=dp_n[i][j][k];
                        if(temp.i<sta[N]-1&&flag[temp.i][temp.j][temp.k]==0)
                        {
                            q.push(temp);
                            flag[temp.i][temp.j][temp.k]=1;
                        }
                    }
                    if(dp_v[temp.i][temp.j][temp.k]<temp_v)
                    {
                        dp_v[temp.i][temp.j][temp.k]=temp_v;
                        dp_n[temp.i][temp.j][temp.k]=dp_n[i][j][k];
                        if(temp.i<sta[N]-1&&flag[temp.i][temp.j][temp.k]==0)
                        {
                            q.push(temp);
                            flag[temp.i][temp.j][temp.k]=1;
                        }
                    }
                }
            }
        }
        for(int j=0; j<N; ++j)
        {
            for(int k=0; k<N; ++k)
            {
                if(dp_v[sta[N]-1][j][k]!=-1)
                {
                    temp.i=sta[N]-1;
                    temp.j=j;
                    temp.k=k;
                    if(ans_1<dp_v[temp.i][temp.j][temp.k])
                    {
                        ans_1=max(ans_1, dp_v[temp.i][temp.j][temp.k]);
                        ans_2=0;
                        ans_2=dp_n[temp.i][temp.j][temp.k];
                    }
                    else if(ans_1==dp_v[temp.i][temp.j][temp.k])
                        ans_2+=dp_n[temp.i][temp.j][temp.k];
                }
            }
        }
        if(N==1)//当N为1时特殊处理
            ans_2=2;
        printf("%I64d %I64d
    ",ans_1,ans_2/2);//因为不算顺序,正反一样,所以应该除2,
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            init();
            scanf("%d%d",&N,&M);
            int v,x,y;
            for(int i=0; i<N; ++i)
            {
                scanf("%d",&val[i]);
            }
            for(int i=0; i<M; ++i)
            {
                scanf("%d%d",&x,&y);
                --x;
                --y;
                g[x][y]=1;
                g[y][x]=1;
            }
            ans_1=0;
            ans_2=0;
            solve();
        }
        return 0;
    }
    

      

  • 相关阅读:
    MVC HTTP 错误 403.14
    web.config connectionStrings 数据库连接字符串的解释(转载)
    bootstrap div 弹出与关闭
    jquery操作select(取值,设置选中)
    VS2013使用EF6与mysql数据库
    php中创建和调用webservice接口示例
    java script 确认框
    mysql中判断记录是否存在方法比较
    根据Unicode编码用C#语言把它转换成汉字的代码
    微软架构师解读Windows Server 2008 R2新特性
  • 原文地址:https://www.cnblogs.com/l1l1/p/8608794.html
Copyright © 2011-2022 走看看