POJ 2288 Islands And Bridges 状态压缩dp+哈密顿回路

题意:n个点 m条边的图,路径价值定义为相邻点乘积,若路路径c[i-1]c[i]c[i+1]中c[i-1]-c[i+1]有边 则价值加上三点乘积
找到价值最大的哈密顿回路,和相应的方法数n<=13.
暴力dfs O(13!) TLE

由于n<13 经典的状态压缩dp [状态] [当前点位置 ][前一点位置] 注意上一个状态必须合法才能进行转移
设状态dp[s][i][j] 当前状态为s,当前点为i上一个点为j的最大价值, ans=max(dp[(1<<n)-1][i])
dp[s][i][j]= S=s^(1<<(i-1))&&dp[S][j][k]状态合法 max(dp[S][j][k]+v[j]*v[k]+v[i]*v[j]*v[k] (c[k],c[i]存在边))
O(2^13*13^3)

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1<<14;
ll n,m,v[15],g[15][15];
ll dp[N][15][15],path[N][15][15];
int main()
{
	int q;
	scanf("%d",&q);
	while(q--)
	{
		memset(dp,-1,sizeof(dp));
		memset(g,0,sizeof(g));
		memset(path,0,sizeof(path));
		scanf("%I64d%I64d",&n,&m);
		for(int i=0;i<n;i++)
			scanf("%I64d",&v[i]);
		int u,V;
		while(m--)
		{
			scanf("%d%d",&u,&V);
			u--,V--;
			g[u][V]=g[V][u]=1;
		}
		if(n==1)
		{
			cout<<v[0]<<‘ ‘<<1<<endl;
			continue;
		}
		//3?ê??ˉ?àáúá?μ??·??dp?μ
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(i==j)	continue;
				if(g[i][j])
				{
					dp[(1<<i)+(1<<j)][i][j]=v[i]+v[j]+v[i]*v[j];
					path[(1<<i)+(1<<j)][i][j]=1;
				}
			}
		}
		for(int s=0;s<(1<<n);s++)
		{
			for(int i=0;i<n;i++)
			{
				if(s&(1<<i)==0)	continue;
				for(int j=0;j<n;j++)
				{
					if(j==i||g[i][j]==0)	continue;
					if((s&(1<<j))==0)	continue;
					for(int k=0;k<n;k++)
					{
						if(j==k||((s&(1<<k))==0)||g[j][k]==0)	continue;
						int add=v[i]+v[i]*v[j];
						if(g[i][k])
							add+=v[i]*v[j]*v[k];
						int S=s^(1<<i);
						if(dp[S][j][k]==-1)	continue;//?°ò???×′ì?òao?·¨ 

						int tmp=dp[S][j][k]+add;
						if(tmp>dp[s][i][j])
							dp[s][i][j]=tmp,path[s][i][j]=path[S][j][k];
						else if(tmp==dp[s][i][j])
							path[s][i][j]+=path[S][j][k];
					}
				}
			}
		}
		ll ans=-1,cnt=0;
		ll s=(1<<n)-1;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(i==j)	continue;
				if(ans<dp[s][i][j])
					ans=dp[s][i][j],cnt=path[s][i][j];
				else if(ans==dp[s][i][j])
					cnt+=path[s][i][j];
			}
		}
		if(ans==-1)
			ans=0,cnt=0;
		cout<<ans<<‘ ‘<<cnt/2<<endl;
	}
	return 0;
}

  

时间: 2024-10-13 20:00:41

POJ 2288 Islands And Bridges 状态压缩dp+哈密顿回路的相关文章

poj 2288 Islands and Bridges_状态压缩dp_哈密尔顿回路问题

题目链接 题目描写叙述:哈密尔顿路问题.n个点,每个点有权值,设哈密尔顿路为 C1C2...Cn,Ci的权值为Vi,一条哈密尔顿路的值分为三部分计算: 1.每个点的权值之和2.对于图中的每一条CiCi+1,加上Vi*Vi+1 3.对于路径中的连续三个点:CiCi+1Ci+2,若在图中,三点构成三角形,则要加上Vi*Vi+1*Vi+2 求一条汉密尔顿路能够获得的最大值,而且还要输出有多少条这种哈密尔顿路. 这道题的状态感觉不是非常难想,由于依据一般的哈密尔顿路问题,首先想到的是设计二维状态,dp[

poj 2288 Islands and Bridges ——状压DP

题目:http://poj.org/problem?id=2288 状压挺明显的: 一开始写了(记忆化)搜索,但一直T: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int const inf=0x3f3f3f3f; int T,n,m,v[15]; ll ans,cnt

POJ 2288 Islands and Bridges 哈密尔顿路 状态压缩DP

找最长的其实是很裸的状态压缩DP,棘手的地方是要统计数量,其实只要再来一个数组存就好. 不过代码比较长,细节要注意的地方毕较多,wa了很多发,还是要仔细啊 用递推和记忆化搜索分别写了一遍 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <

POJ2288Islands and Bridges(状态压缩DP,求最大路和走条数)

Islands and Bridges Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 8845   Accepted: 2296 Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that i

poj 2288 Islands and Bridges

题意: 给你一个双向连通图,求 获得权值最大 的 哈密顿通路的 权值 和 这个权值对应的数目: 其中权值计算方法是  列如 ABCD  权值是a+b+c+d+ab+bc+cd 如果 A,B,C  和B,C,D 可构成三角形分别加上abc,bcd: 这个题 和poj 3311  很相像: 那个需要记录一个最后到达的地方   这个需要记录俩个罢了 DP[i][a][b]其中 i  二进制 中1表示这个点走过了   最后走的的 的是b>>a 因为对于已经走过了{1,2,3,4,,5,6,..,N}

POJ2288:Islands and Bridges(状态压缩)

Description Given a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that it visits each island exactly once. On our map, there is also a positive integer value associated with e

poj 3254 Corn Fields ,状态压缩DP

题目链接 题意: 一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) state[i] 表示对于一行,保证不相邻的方案 状态:dp[i][ state[j] ]  在状态为state[j]时,到第i行符合条件的可以放牛的方案数 状态转移:dp[i][ state[j] ] =Sigma dp[i-1][state'] (state'为符合条

POJ 1038 Bugs Integrated, Inc. 状态压缩DP

题目来源:1038 Bugs Integrated, Inc. 题意:最多能放多少个2*3的矩形 思路:状态压缩DP啊 初学 看着大牛的代码搞下来的  总算搞懂了 接下来会更轻松吧 3进制代表前2行的状态(i行和i-1行)1代表i-1行占位 2代表i行占位 i-1不管有没有占位都不会影响的0代表i行和i-1行都空闲 然后枚举状态dfs更新状态 话说就不能没写深搜了 有点不会了 #include <cstdio> #include <cstring> #include <alg

[POJ 2411] Mondriaan&#39;s Dream 状态压缩DP

题意 给定一个 n * m 的矩形. 问有多少种多米诺骨牌覆盖. n, m <= 11 . 实现 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 #define LL long long 7 inline