题目:http://poj.org/problem?id=2288
状压挺明显的;
一开始写了(记忆化)搜索,但一直T;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 "); else printf("%lld %lld ",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 ",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 ");// else printf("%I64d %I64d ",ans,cnt/2);// } return 0; }