HDU 1668 POJ 2288 Islands and Bridges

来源:互联网 发布:彩票统计分析软件 编辑:程序博客网 时间:2024/05/22 15:14

以下解题思路摘自:http://www.cnblogs.com/jackge/archive/2013/05/24/3096162.html

取dp[state][i][j]表示state状态下倒数第二个岛为i,最后一个岛为j时的最优解,num[state][i][j]为相应的路径数目,其中state的二进制表示的i位为1表示岛i被访问过,反之为0。
则显然当有边(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。
如果状态(state,i,j)可达,检查岛k,如果此时k没有被访问过并且有边(j,k)存在,则做如下操作:
1)设tmp为下一步访问岛k时获得的总利益,r=state+(1<<k)。
2)如果tmp>dp[r][j][k],表示此时可以更新到更优解,则更新
    dp[r][j][k]=tmp,num[r][j][k]=num[state][i][j]。
3)如果tmp==dp[r][j][k],表示此时可以获得达到局部最优解的更多方式,则更新:
    num[r][j][k]+=num[state][i][j]。
最后检查所有的状态((1<<n)-1,i,j),叠加可以得到最优解的道路数。
需要注意的是,题目约定一条路径的两种行走方式算作一种,所以最终结果要除2。

以下代码实现为我自己写的:

#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <map>#include <vector>#include <cmath>#include <stack>#include <queue>#include <cstdlib>#include <algorithm>using namespace std;typedef __int64 int64;typedef long long ll;#define M 100005#define max_inf 0x7f7f7f7f#define min_inf 0x80808080#define mod 1000000007int n , m , dp[1<<13][13][13] , val[15];int64 sum[1<<13][13][13];bool Map[15][15];void Solve(){int i , j , k , l , up = 1<<n , next;memset(dp , -1 , sizeof dp);memset(sum , 0 , sizeof sum);//给相邻点赋初值for (i = 0 ; i < n ; i++){for (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];sum[(1<<i)+(1<<j)][i][j] = 1;}}}for (i = 1 ; i < up ; i++){for (j = 0 ; j < n ; j++){if ( !(i & (1<<j)) )continue;for (k = 0 ; k < n ; k++){if (j == k)continue;if ( !(i & (1<<k)) )continue;if (dp[i][j][k] < 0)continue;//找寻下一个可以连接的点for (l = 0 ; l < n ; l++){if (l == j || l == k)continue;if (i & (1<<l))continue;if (!Map[k][l])continue;int tmp = dp[i][j][k]+val[l]+val[k]*val[l];if (Map[j][l])tmp += val[j]*val[k]*val[l];next = i+(1<<l);if (dp[next][k][l] == tmp)sum[next][k][l] += sum[i][j][k];else if (dp[next][k][l] < tmp){dp[next][k][l] = tmp;sum[next][k][l] = sum[i][j][k];}}}}}int MAX = -1;int64 ans = 0;for (i = 0 ; i < n ; i++){for (j = 0 ; j < n ; j++){if (i == j)continue;if (MAX < dp[up-1][i][j]){MAX = dp[up-1][i][j];ans = sum[up-1][i][j];}else if (MAX == dp[up-1][i][j])ans += sum[up-1][i][j];}}if (MAX < 0)printf("0 0\n");else printf("%d %I64d\n",MAX , ans/2);}int main(){int t , i;scanf("%d",&t);while (t--){scanf("%d%d",&n,&m);memset(Map , 0 , sizeof Map);for (i = 0 ; i < n ; i++)scanf("%d",val+i);for (i = 0 ; i < m ; i++){int a , b;scanf("%d%d",&a,&b);a--,b--;Map[a][b] = Map[b][a] = 1;}if (n == 1)printf("%d 1\n",val[0]);elseSolve();}return 0;}


 

 

原创粉丝点击