这倒题太坑了。。。简直。。。明明没有错误的代码就是A不了。。
题目分析另
f(state,i,j)
表示在状态为state的情况下当前在i点前一个点是j点的所能够得到的最大的乘积那么很容易发现
f(state+(1<<k),k,i)=f(state,i,j)+v[k]+v[k]×v[i]|G[j][k]=0
或者
f(state+(1<<k),k,i)=f(state,i,j)+v[k]+v[k]×v[i]+v[k]×v[i]×v[j]|G[j][k]=1
其中G表示i,j是否连通,那么最终的答案就是
max{f((1<<n)−1,i,j)}
这里i和j是需要枚举的,然后怎么寻找方案数量呢定义
g(state,i,j)
表示在状态为state的情况下当前在i点前一个点是j点的所能够得到的最大的乘积的方案数量那么
g(state+(1<<k),k,i)=g(state,i,j)|f(state+(1<<k),k,i)<f(state,i,j)+v[k]+v[k]×v[i]
在相等条件的情况下的时候
g(state+(1<<k),k,i)+=g(state,i,j)
剩下的就是注意代码了,如果一直Ac不了,删了重新写吧。。。
#include <cstdio>
#include <cstring>
using namespace std;
/*********/
typedef long long LL;
const int MAXN = 13;
int Map[MAXN+2][MAXN+2];
LL way[int(1<<MAXN)+2][MAXN+2][MAXN+2];
LL dp[int(1<<MAXN)+2][MAXN+2][MAXN+2];
LL v[MAXN+2], n, m;
/*********/
void DP(){
memset(dp, -1, sizeof dp);
memset(way, 0, sizeof way);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j) continue;
if(!Map[i][j]) continue;
dp[(1<<i)+(1<<j)][i][j] = v[i] * v[j] + v[i] + v[j];
way[(1<<i)+(1<<j)][i][j] = 1;
}
}
int Max = 1 << n;
for(int state=0; state<Max; state++){
for(int i=0; i<n; i++){
if((state & (1 << i)) == 0) continue;
for(int j=0; j<n; j++){
if((state & (1 << j)) == 0) continue;
if(i == j) continue;
if(!Map[i][j]) continue;
if(dp[state][j][i] == -1) continue;
for(int k=0; k<n; k++){
if(k == i || k == j) continue;
if(!Map[j][k]) continue;
if((state & (1 << k)) != 0) continue;
int _state = state + (1 << k);
int tmp = dp[state][j][i] + v[k] + v[k] * v[j];
if(Map[i][k]) tmp += v[k] * v[j] * v[i];
if(tmp > dp[_state][k][j]){
dp[_state][k][j] = tmp;
way[_state][k][j] = way[state][j][i];
}else if(tmp == dp[_state][k][j])
way[_state][k][j] += way[state][j][i];
}
}
}
}
long long ans=-1, wsum=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i == j || !Map[i][j]) continue;
if(dp[Max-1][i][j] > ans){
ans = dp[Max-1][i][j];
wsum = way[Max-1][i][j];
}else if(dp[Max-1][i][j] == ans)
wsum += way[Max-1][i][j];
}
}
printf("%I64d %I64d\n", ans==-1?0:ans, wsum/2);
}
int main(){
int T, u, vp;
scanf("%d", &T);
while(T--){
memset(Map, 0, sizeof Map);
scanf("%I64d%I64d", &n, &m);
for(int i=0; i<n; i++) scanf("%I64d", &v[i]);
for(int i=0; i<m; i++){
scanf("%d%d", &u, &vp);
u --; vp --;
Map[u][vp] = Map[vp][u] = 1;
}
if(n == 1) printf("%I64d 1\n", v[0]);
else DP();
}
return 0;
}