pku3229 The Best Travel Design 状压DP

题意太过于坑爹,数据也迷之坑,反正坑的不行。重边啊题目说是整数给小数啊什么鬼都出来了= =

嘛直接状压,伪TSP问题,floyed做完prework一切好办

Problem: 3229		User: BPM136
Memory: 5092K		Time: 1047MS
Language: G++		Result: Accepted

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 200
#define DB double
#define UL unsigned long
#define inf 1000000007
double eps=0.00000001;
DB f[1<<16][17];
DB map[N][N];
int n,m;
DB stay[N],sumt,K;
int res,ans;
int x,y,kind;DB len;
bitset<N>e;

void init()
{
	fo(i,0,n-1)
	{
		fo(j,0,n-1)
		if(i!=j)map[i][j]=inf;
		else map[i][j]=0;
	}
	res=0;sumt=K*(12.0);ans=-1;
//	printf("%lf\n",sumt);
	fo(i,1,m)
	{
		scanf("%d",&x);
		res+=1<<(x-1);
	}
	fo(i,0,n-1)scanf("%lf",&stay[i]);
	while(scanf("%d%d%lf%d",&x,&y,&len,&kind)!=EOF&&(x||y||len||kind))
	{
		x--,y--;
		DB t=len*(1.0)/(kind?120.0:80.0);
		map[x][y]=map[y][x]=min(map[x][y],t);
	}
	fo(i,0,n-1)
	{
		fo(j,0,(1<<n)-1)
		f[j][i]=-1;
	}
}

void floyed()
{
	fo(k,0,n-1)
	{
		fo(i,0,n-1)
		if(i!=k)
		{
			fo(j,0,n-1)
			if(j!=k&&i!=j)
			if(map[i][k]+map[k][j]-map[i][j]<eps)
			map[i][j]=map[i][k]+map[k][j];
		}
	}
}

DB SC_DP(UL now,int x)
{
	if(f[now][x]+eps>-eps)return f[now][x];
	int st=now-(1<<x),status=now-(1<<x);DB ret=inf;
	while(st)
	{
		int k=st&(-st);
		int pos=log(k+0.5)/log(2.0);
		if(x==pos)puts("stop!!!!!!!!!");
		DB anss=SC_DP(status,pos);
		if(anss>-eps)
		{
			DB zans=anss+map[pos][x]+stay[x];
			if(zans-ret<eps)ret=zans;
		}
		st-=k;
	}
	if(((now&res)==res)&&ret+map[x][0]<=sumt)
	{
		e=now;
		int anss=e.count();
		ans=max(ans,anss);
	}
//	e=now;
	return f[now][x]=ret;
}
		

int main()
{
	while(scanf("%d%d%lf",&n,&m,&K)!=EOF&&(x+m+K)>eps)
	{
		init();
		floyed();
		fo(i,0,n-1)
		if(map[0][i]-inf<eps)
		f[(1<<i)][i]=map[0][i]+stay[i];
		fo(i,0,n-1)SC_DP((1<<n)-1,i);
//		SC_DP((1<<n)-1,0);
//		cout<<"status:"<<res<<' ';printf("sumtime:%d\n",sumt);
		if(ans<0)printf("No Solution\n");
		else printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值