经典的TSP问题变种。状态为f[i][j][k],表示经过二进制数i所指的哈密顿路(第bi位为1表示经过该点,为0表示不经过该点),倒数第二个点为j,最后一个点为k。.value表示最大权值,.num表示能走出最大权值的路径数。若图中k到p有边,f[i][j][k]则转移到f[i'][k][p]。i' == i | (1 << p)。

/************************************************************************* 
Author: WHU_GCC 
Created Time: 2007-8-20 14:49:47 
File Name: pku2288.cpp 
Description:  
***********************************************************************
*/
 
#include 
<iostream> 
using namespace std; 
#define out(x) (cout<<#x<<": "<<x<<endl) 
const int maxint=0x7FFFFFFF; 
typedef 
long long int64; 
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL; 
template
<class T>void show(T a, int n){for(int i=0; i<n; ++i) cout<<a[i]<<' '; cout<<endl;} 
template
<class T>void show(T a, int r, int l){for(int i=0; i<r; ++i)show(a[i],l);cout<<endl;} 

typedef 
struct state_t 
{ 
    int64 value, num; 
}
; 

int n, m; 
int64 c[
13]; 
int g[13][13]; 
state_t f[
1 << 13][13][13]; 

void dp(int64 &ans_value, int64 &ans_num) 
{ 
    
if (n == 1) 
    
{ 
        ans_value 
= c[0]; 
        ans_num 
= 2; 
        
return; 
    }
 
     
    memset(f, 
0, sizeof(f)); 
    
for (int i = 0; i < n; i++) 
        
for (int j = 0; j < n; j++) if (g[i][j] != 0) 
        
{ 
            f[(
1 << i) | (1 << j)][i][j].value = c[i] + c[j] + c[i] * c[j]; 
            f[(
1 << i) | (1 << j)][i][j].num = 1; 
        }
 
    
for (int i = 0; i < (1 << n); i++) 
    
{ 
        
for (int j = 0; j < n; j++) if ((i >> j) & 1) 
            
for (int k = 0; k < n; k++) if ((i >> k) & 1) if (f[i][j][k].value != 0) 
            
{ 
                
for (int p = 0; p < n; p++) if (((i >> p) & 1) == 0 && g[k][p] != 0) 
                
{ 
                    int64 t 
= c[p] + c[p] * c[k]; 
                    
if (g[j][p] != 0) t += c[j] * c[k] * c[p]; 
                    
if (f[i][j][k].value + t > f[i | (1 << p)][k][p].value) 
                    
{ 
                        f[i 
| (1 << p)][k][p].value = f[i][j][k].value + t; 
                        f[i 
| (1 << p)][k][p].num = f[i][j][k].num; 
                    }
 
                    
else if (f[i][j][k].value + t == f[i | (1 << p)][k][p].value) 
                        f[i 
| (1 << p)][k][p].num += f[i][j][k].num; 
                }
 
            }
 
    }
 
    ans_value 
= 0; 
    ans_num 
= 0; 
    
for (int i = 0; i < n; i++) 
        
for (int j = 0; j < n; j++) 
            
if (f[(1 << n) - 1][i][j].value > ans_value) 
            
{ 
                ans_value 
= f[(1 << n) - 1][i][j].value; 
                ans_num 
= f[(1 << n) - 1][i][j].num; 
            }
 
            
else if (f[(1 << n) - 1][i][j].value == ans_value) 
                ans_num 
+= f[(1 << n) - 1][i][j].num; 
}
 

int main() 
{ 
    
int ca; 
    
for (scanf("%d", &ca); ca--;) 
    
{ 
        scanf(
"%d%d", &n, &m); 
        
for (int i = 0; i < n; i++) 
            scanf(
"%lld", &c[i]); 
        memset(g, 
0, sizeof(g)); 
        
for (int i = 0; i < m; i++) 
        
{ 
            
int t1, t2; 
            scanf(
"%d%d", &t1, &t2); 
            t1
--; 
            t2
--; 
            g[t1][t2] 
= g[t2][t1] = 1; 
        }
 
        int64 ans1, ans2; 
        dp(ans1, ans2); 
        cout 
<< ans1 << " " << ans2 / 2 << endl; 
    }
 
    
return 0; 
}
 
posted on 2007-08-28 20:47 Felicia 阅读(899) 评论(2)  编辑 收藏 引用 所属分类: 动态规划
Comments