poj 2288 Islands and Bridges ——状压DP

题目:http://poj.org/problem?id=2288

状压挺明显的;

一开始写了(记忆化)搜索,但一直T;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const inf=0x3f3f3f3f;
int T,n,m,v[15];
ll ans,cnt,f[1<<13];
bool mp[15][15];
void dfs(int z,int x,int y,ll w)
{
    if(w<f[z])return;
    f[z]=w;
    if(z==(1<<n)-1)
    {
        if(w>ans)ans=w,cnt=1;
        else if(w==ans)cnt++;
        return;
    }
    for(int i=1;i<=n;i++)
        if((z&(1<<(i-1)))==0)
            dfs(z|(1<<(i-1)),y,i,w+v[i]+v[y]*v[i]+(mp[x][i]?v[x]*v[y]*v[i]:0));
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(f,0,sizeof f);
        memset(mp,0,sizeof mp); 
        ans=-inf; cnt=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&v[i]);
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            mp[x][y]=1; mp[y][x]=1;
        }
        dfs(0,0,0,0);
        if(cnt==0)printf("0 0\n");
        else printf("%lld %lld\n",ans,cnt/2);
    }
    return 0;
}

于是改成刷表,注意点细节就行了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const inf=0x3f3f3f3f;
int T,n,m,v[15];
ll ans,cnt,f[1<<13|1][15][15],s[1<<13|1][15][15];
bool mp[15][15];
void dp()
{
    memset(f,-1,sizeof f);
    memset(s,0,sizeof s);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)    if(mp[i][j])
        {    
            int p=((1<<(i-1))|(1<<(j-1)));
            f[p][i][j]=v[i]+v[j]+v[i]*v[j]; s[p][i][j]=1;
        }
    for(int p=3;p<(1<<n);p++)
        for(int i=1;i<=n;i++)    if(!(p&(1<<(i-1))))
            for(int j=1;j<=n;j++)    if(p&(1<<(j-1)))
                for(int k=1;k<=n;k++)     if((p&(1<<(k-1)))&&j!=k&&mp[i][k]&&f[p][j][k]!=-1)
                {
                    ll tmp=f[p][j][k]+v[i]+v[k]*v[i]+(mp[j][i]?v[j]*v[k]*v[i]:0);
                    int tp=(p|(1<<(i-1)));
                    if(tmp>f[tp][k][i]) f[tp][k][i]=tmp,s[tp][k][i]=s[p][j][k];
                    else if(tmp==f[tp][k][i])s[tp][k][i]+=s[p][j][k];
                }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(mp,0,sizeof mp); 
        ans=-inf; cnt=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&v[i]);
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            mp[x][y]=1; mp[y][x]=1;
        }
        if(n==1){printf("%d %d\n",v[1],1); continue;}//
        dp(); int mx=(1<<n)-1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)    if(i!=j)
            {
                if(f[mx][i][j]==ans)cnt+=s[mx][i][j];
                else if(f[mx][i][j]>ans)ans=f[mx][i][j],cnt=s[mx][i][j];
            }
        if(cnt==0)printf("0 0\n");//
        else printf("%I64d %I64d\n",ans,cnt/2);//
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Zinn/p/9367593.html
今日推荐