[DP] boj1670

/*
Description
dalong最近对汉密尔顿路很感兴趣,现在他给你一个包含n个点的无向图,
对于一条路径a1->a2...->ak,他定义这条路径的花费值value = a1*a2*...*ak。
汉密尔顿路定义:给定图G,若存在一条路,经过图中每个结点恰好一次,这条路称作汉密尔顿路。
dalong现在给你一个无向图,包含n个点和m条边,他请你帮他找到一条花费值最小的汉密尔顿路。
数据范围:
1 <= n <= 16 , 1 <= m <= n^2;
Input
多组测试数据
对于每组数据,输入的第一行是两个数n和m,表示有n个点和m条边。
后面m行,每行三个数a,b,c。表示a和b之间有一条边,长度为c(1 <=a , b <= n 且 a != b , 1 <= c <= 2 ^ 30, c保证是2的k次幂)
Output
对于每组测试数据,如果汉密尔顿路径存在,输出一行,最小的花费值。如果不存在,输出"Poor Dalong"
 */
import java.math.BigInteger;
import java.util.Scanner;
public class Main 
{
	static int MIN(int a,int b){return (a>b)? b:a;}
	static int MAX(int a,int b){return (a<b)? b:a;}
	static int Max_Int=200000000;
	public static void main(String[] args)
	{
		Scanner cin=new Scanner(System.in);
		int a[][]=new int [20][20],dp[][]=new int [20][(1<<17)+100];
		int p[]=new int [200];
		while(cin.hasNextInt())
		{
			int n,m;
			n=cin.nextInt();m=cin.nextInt();
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					a[i][j]=(i==j)? 0:Max_Int;
			for(int i=1;i<=m;i++)
			{
				int x,y,len,cnt=-1;
				x=cin.nextInt();y=cin.nextInt();len=cin.nextInt();	
				while(len>0)
				{
					len/=2;
					cnt++;
				}
				a[x][y]=MIN(a[x][y], cnt);
				a[y][x]=a[x][y];
			}
			for(int i=1;i<=n;i++)
				for(int j=1;j<=(1<<n)-1;j++)
					dp[i][j]=Max_Int;
			for(int i=1;i<=n;i++)
				dp[i][1<<(i-1)]=0;
			for(int i=1;i<=n-1;i++)
			{
				for(int j=1;j<=(1<<n)-1;j++)
				{
					int cnt=0;
					for(int k=1;k<=n;k++)
						if((j&(1<<(k-1)))!=0)
						{
							p[++cnt]=k;
						}
					if(cnt==i)
					{
						int sum=0;
						for(int k=1;k<=cnt;k++)
							sum+=(1<<(p[k]-1));
						for(int k=1;k<=n;k++)
							if((sum&(1<<(k-1)))==0)
							{
								for(int l=1;l<=cnt;l++)
								{
									if(dp[k][sum+(1<<(k-1))]>dp[p[l]][sum]+a[p[l]][k])
									{
										dp[k][sum+(1<<(k-1))]=dp[p[l]][sum]+a[p[l]][k];
									}	
								}
							}
					}
				}
			}
			int Ans=Max_Int;
			for(int i=1;i<=n;i++)
				Ans=MIN(Ans, dp[i][(1<<n)-1]);
			if(Ans!=Max_Int)
			{
				BigInteger c=BigInteger.ONE;
				while(Ans-->0)
					c=c.multiply(BigInteger.valueOf(2));
				System.out.println(c);
			}
			else System.out.println("Poor Dalong");
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值