zoukankan      html  css  js  c++  java
  • poj 2288

    传送门

    解题思路

    状压dp,记录路径条数,dp[S][i][j]表示状态为S,前一个点是i,再前一个点是j的最大值,然后在开个一样的数组记录方案数,时间复杂度O(2^n*n^2),注意要用long long,还有数据有一个点的情况。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define int long long
    
    using namespace std;
    const int N = 14;
    typedef long long LL;
    const int inf = -0x3f3f3f3f;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int q,n,m,a[N][N],val[N];
    LL dp[1<<N][N][N],num[1<<N][N][N],ans,ans_num;
    
    signed main(){
        q=rd();
        while(q--){
            ans=0,ans_num=0;
            memset(a,0,sizeof(a));
            memset(dp,-0x3f,sizeof(dp));
            memset(num,0,sizeof(num));
            n=rd(),m=rd();register int x,y;
            for(register int i=1;i<=n;i++) val[i]=rd();
            for(register int i=1;i<=m;i++) {
                x=rd(),y=rd();
                a[x][y]=a[y][x]=1;
            }
            dp[0][0][0]=0;num[0][0][0]=1;
            for(register int i=0;i<(1<<n)-1;i++)
                for(register int j=1;j<=n;j++)if(!((1<<j-1)&i))
                    for(register int k=0;k<=n;k++)if(((1<<k-1)&i && a[j][k]) || k==0)
                        for(register int p=0;p<=n;p++)if(((1<<p-1)&i && a[p][k]) || p==0){
                            if(dp[i][k][p]==-inf) continue;
                            LL now=dp[i][k][p]+val[j]+(LL)val[j]*val[k];
                            if(a[j][p]) now+=(LL)val[j]*val[k]*val[p];
                            if(dp[i|(1<<j-1)][j][k]==now)
                                num[i|(1<<j-1)][j][k]+=num[i][k][p];
                            else if(dp[i|(1<<j-1)][j][k]<now){
                                dp[i|(1<<j-1)][j][k]=now;
                                num[i|(1<<j-1)][j][k]=num[i][k][p];
                            }
                        }
            for(register int i=1;i<=n;i++)
                for(register int j=1;j<=n;j++)  
                    if(a[i][j]) {
                        if(dp[(1<<n)-1][i][j]>ans) {ans=dp[(1<<n)-1][i][j];ans_num=num[(1<<n)-1][i][j];}
                        else if(dp[(1<<n)-1][i][j]==ans) ans_num+=num[(1<<n)-1][i][j]; 
                    }
            if(n==1 && m==0) {ans=val[1];ans_num=2;}
            cout<<ans<<" "<<ans_num/2<<endl;
        }
        return 0;
    }
  • 相关阅读:
    微信公众平台接口测试账号申请
    Windows平台下tomcat+java的web程序持续占cpu问题调试
    mysql存储过程基础
    Mysql权限控制
    MySQL开启federated引擎实现数据库表映射
    JAVA中Set集合--HashSet的使用
    在js中嵌套java代码
    MySql计算两个日期的时间差函数
    关于easyui combobox下拉框实现多选框的实现
    利用excel办公软件快速拼凑sql语句
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676834.html
Copyright © 2011-2022 走看看