题意:给你一个图和每个点的价值,边权值为连接两点权值的积,走哈密顿通路,若到达的点和上上个点相连则价值加三点乘积,求哈密顿通路的最大价值,和最大价值哈密顿通路的条数。
分析:开始看这个题很吓人,但想想这个题状态好确定dp[i][j][k]表示 i已走过点的情况,当前点为j前一点为k所产生的最大价值,枚举所有可行的情况即可,接着想怎么求条数啊,
纠结了好久,才发现和在求价值时若和原来的价值相等,则加原来状态所包含的条数,若更新了最大值,这数量为当前状态的条数,还要注意两条完全反向的路径看成一条路径。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) #define N 1<<13 const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int n,m,con[15][15],v[15]; ll dp[N][15][15],num[N][15][15]; void solve(){ memset(dp,-1,sizeof(dp)); memset(num,0,sizeof(num)); int cas=(1<<n)-1; dp[0][0][0]=0; for(int i=1;i<=n;++i){ dp[1<<(i-1)][0][i]=v[i]; num[1<<(i-1)][0][i]=1; } for(int i=1;i<=cas;++i){ for(int j=1;j<=n;++j){ if(!(i&(1<<(j-1))))continue; for(int k=0;k<=n;++k){ if(j==k)continue; if(k==0&&!(i&(1<<(j-1)))||k!=0&&!(i&(1<<(k-1))))continue; if(dp[i][k][j]==-1)continue; for(int l=1;l<=n;++l){ if(!(i&(1<<(l-1)))&&con[j][l]){ int t=i+(1<<(l-1)); ll tot=v[l]*(v[j]+1); if(con[l][k]) tot+=v[k]*v[j]*v[l]; tot+=dp[i][k][j]; if(dp[t][j][l]<tot){ dp[t][j][l]=tot; num[t][j][l]=num[i][k][j]; } else if(dp[t][j][l]==tot){ num[t][j][l]+=num[i][k][j]; } } } } } } ll maxv=-1,sum=0; for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) maxv=max(maxv,dp[cas][i][j]); if(maxv==-1) printf("0 0\n"); else{ for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) if(maxv==dp[cas][i][j]) sum+=num[cas][i][j]; printf("%I64d %I64d\n",maxv,sum/2?sum/2:1); } } int main() { int q; scanf("%d",&q); while(q--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&v[i]); int x,y; memset(con,0,sizeof(con)); while(m--){ scanf("%d%d",&x,&y); con[x][y]=1; con[y][x]=1; } solve(); } return 0; }
时间: 2024-11-25 20:56:26