经典的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, 
0sizeof(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) & 1if (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, 
0sizeof(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 阅读(814) 评论(2)  编辑 收藏 引用 所属分类: 动态规划
Comments

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理