HDU 1668 POJ 2288 Islands and Bridges

以下解題思路摘自: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 1000000007

int 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]);
		else
			Solve();
	}
	return 0;
}


 

 

發佈了98 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章