HIT暑期集训 状压与优化DP

B    POJ 2288

题解参考:https://www.cnblogs.com/jackge/archive/2013/05/24/3096162.html

DP还是不会。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 15
#define mod 100000000
typedef long long ll;
using namespace std;
int n,m,mp[maxn][maxn],val[maxn];
int dp[1<<13][maxn][maxn],ans1;
ll cnt[1<<13][maxn][maxn],ans2;
int main()
{
    int T,i,j,k,x,y,tmp; 
    scanf("%d",&T);
    while (T--)
    {
        memset(mp,0,sizeof(mp));
        memset(cnt,0,sizeof(cnt));
        memset(dp,-1,sizeof(dp));
        scanf("%d%d",&n,&m);
        for (i=0;i<n;i++) scanf("%d",&val[i]);
        for (i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            x--;y--;
            mp[x][y]=mp[y][x]=1;
        }
        if(n==1)
        {
            printf("%d 1\n",val[0]);
            continue;
        }
        for (i=0;i<n;i++)
        for (j=0;j<n;j++)
        {
            if (i==j || !mp[i][j]) continue;
            dp[(1<<i)|(1<<j)][i][j]=val[i]+val[j]+val[i]*val[j];
            cnt[(1<<i)|(1<<j)][i][j]=1;
        }
        for (i=0;i<(1<<n);i++)
        for (j=0;j<n;j++)
        {
            if (!(i&(1<<j))) continue;
            for (k=0;k<n;k++)
            {
                if (!mp[j][k] || j==k || !(i&(1<<k)) || dp[i][j][k]==-1) continue;
                for (x=0;x<n;x++)
                {
                    if (!mp[k][x] || x==j || x==k || (i&(1<<x))) continue;
                    tmp=dp[i][j][k]+val[x]+val[k]*val[x];
                    if (mp[j][x]) tmp+=val[j]*val[k]*val[x];
                    if (dp[i|(1<<x)][k][x]<tmp)
                    {
                        dp[i|(1<<x)][k][x]=tmp;
                        cnt[i|(1<<x)][k][x]=cnt[i][j][k];
                    }
                    else if (dp[i|(1<<x)][k][x]==tmp) cnt[i|(1<<x)][k][x]+=cnt[i][j][k];
                }
            }    
        }
        ans1=0;ans2=0;
        for (i=0;i<n;i++)
        for (j=0;j<n;j++)
        {
            if (i==j || !mp[i][j]) continue;
            if (ans1<dp[(1<<n)-1][i][j])
            {
                ans1=dp[(1<<n)-1][i][j];
                ans2=cnt[(1<<n)-1][i][j];
            }
            else if (ans1==dp[(1<<n)-1][i][j]) ans2+=cnt[(1<<n)-1][i][j];
        }     
        printf("%d %lld\n",ans1,ans2/2);
    } 
    return 0;
}
View Code

E    POJ 1821

F    POJ 3017

G    POJ 3744

H    POJ 2373

posted @ 2020-08-25 22:20  lsy_kk  阅读(142)  评论(0编辑  收藏  举报