First of all can think of is like a template pressure dp
Take dp [state, i, j] represents the islands penultimate state is state i, the last one is the optimal solution when the island j,
num [state, i, j] for the corresponding number of paths, wherein State i-bit binary representation for i is 1 showing island visited, and 0 otherwise.
When it is clear that there are edges (i, j) exists, the initial value can be assigned the following:
** DP [(<<. 1 I) + (J <<. 1), I, J] = Val [I] Val + [ j] + val [i] * val [j], num [(1 << i) + (1 << j), i, j] = 1.
If the status (state, i, j) up to check island k , if at this time k has not been accessed and have edges (J, k) : is present, the following operations
1) provided tmp when the next access island k the total benefits derived, r = State | (1 << k) .
2) If tmp> DP [R & lt, J, K] , represents a case can be updated to a more optimal solution, is updated:
DP [I, J, K] = tmp; **
num [r, j, k] = num [state, i, j].
3) If tmp == DP [R & lt, J, K] , can be obtained at this time indicates more ways to achieve local optimal solution, is updated:
NUM [R & lt, J, K] + = NUM [State, I, J ].
Similar to the shortest count
All final check the status ((n-<<. 1) -1, I, J) , can be superimposed on the optimal solution of the number of roads.
Note that, the subject agreed path of two kinds regarded as a kind of walking, so the final result to be divided by 2 .
code (written in a very clear, very clear, the equation looks very scary, is not difficult):
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m;
int val[15],map[13][13];
int dp[1<<13][13][13]; //dp[state][i][j]表示state状态下倒数第二个岛为i,最后一个岛为j时的最优解
long long num[1<<13][13][13]; //num[state][i][j]为相应的路径数目
int main(){
//freopen("input.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&val[i]);
memset(map,0,sizeof(map));
int u,v;
while(m--){
scanf("%d%d",&u,&v);
u--;v--;
map[u][v]=map[v][u]=1;
}
if(n==1){
printf("%d 1\n",val[0]);
continue;
}
memset(dp,-1,sizeof(dp));
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j && map[i][j]){
dp[(1<<i)|(1<<j)][i][j]=val[i]+val[j]+val[i]*val[j];
num[(1<<i)|(1<<j)][i][j]=1;
}
for(int i=0;i<(1<<n);i++)
for(int j=0;j<n;j++)
if((i&(1<<j))!=0)
for(int k=0;k<n;k++)
if(map[j][k] && j!=k && (i&(1<<k))!=0 && dp[i][j][k]!=-1)
for(int x=0;x<n;x++)
if(map[k][x] && j!=x && k!=x && (i&(1<<x))==0){
int tmp=dp[i][j][k]+val[x]+val[k]*val[x];
if(map[j][x])
tmp+=val[j]*val[k]*val[x];
if(dp[i|(1<<x)][k][x]<tmp){
dp[i|(1<<x)][k][x]=tmp;
num[i|(1<<x)][k][x]=num[i][j][k];
}else if(dp[i|(1<<x)][k][x]==tmp)
num[i|(1<<x)][k][x]+=num[i][j][k];
}
int ans1=0;
long long ans2=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j && map[i][j]){
if(ans1<dp[(1<<n)-1][i][j]){
ans1=dp[(1<<n)-1][i][j];
ans2=num[(1<<n)-1][i][j];
}else if(ans1==dp[(1<<n)-1][i][j])
ans2+=num[(1<<n)-1][i][j];
}
cout<<ans1<<" "<<ans2/2<<endl;
}
return 0;
}