P9813 [CCC 2015 S4] Convex Hull 题解

P9813 [CCC 2015 S4] Convex Hull 题解

前置芝士

最短路

题目

注意题目数据范围有误,存在 h i = 0 h_i=0 hi=0 的情况,不知道会不会修。

思路

h i > 0 h_i>0 hi>0

首先,拿到一道题目要观察一下数据范围,我们发现 k < = 200 k<=200 k<=200,很小。

由于 h i > 0 h_i>0 hi>0 ,所以每走一次 ∑ h i \sum h_i hi 都是不断增加的,这就意味着它具有 无后效性,考虑 dp。

f [ a ] [ b ] f[a][b] f[a][b] 表示 ∑ h i = a \sum h_i=a hi=a 时,到 b b b 节点的 t i t_i ti 的最小值。

#include<bits/stdc++.h>
using namespace std;typedef long long ll;
ll CCF,n,m,u,uu,bq1,bq2,s,t,f[205][2005],ans=0x3f3f3f3f;
struct cyl{ll u,bq1,bq2;cyl(ll u,ll bq1,ll bq2):u(u),bq1(bq1),bq2(bq2){};};//这里用了一下析构函数,可以自己去了解一下。
vector<cyl>v[2005];
int main(){
	memset(f,0x3f,sizeof(f));
	scanf("%lld%lld%lld",&CCF,&n,&m);
	for(int i=1;i<=m;i++)scanf("%lld%lld%lld%lld",&u,&uu,&bq1,&bq2),v[u].push_back(cyl(uu,bq1,bq2)),v[uu].push_back(cyl(u,bq1,bq2));
	scanf("%lld%lld",&s,&t);
	f[0][s]=0;
	for(int i=0;i<CCF;i++)
		for(int j=1;j<=n;j++)
			for(cyl k:v[j])
				if(i+k.bq2<CCF)f[i+k.bq2][k.u]=min(f[i+k.bq2][k.u],f[i][j]+k.bq1);
	for(int i=0;i<CCF;i++)ans=min(ans,f[i][t]);
	return printf("%lld",((ans==0x3f3f3f3f)?-1:ans)),0;
}

64 p t s 64pts 64pts

100pts

对于 h i = 0 h_i=0 hi=0 的情况,打个最短路处理一下就可以了。其实就是分层图最短路。

我用的是 SPFA ,理论上可以卡过去,不过截至我写这篇文章的时候还是能 AC 的。

#include<bits/stdc++.h>
using namespace std;typedef long long ll;
ll CCF,n,m,u,uu,bq1,bq2,s,t,f[205][2005],rd[205][2005],ans=0x3f3f3f3f;
struct cyl{ll u,bq1,bq2;cyl(ll u,ll bq1,ll bq2):u(u),bq1(bq1),bq2(bq2){};};
vector<cyl>v[2005],e[2005];queue<ll>q;
int main(){
//freopen("path.in","r",stdin);freopen("path.out","w",stdout);
	memset(f,0x3f,sizeof(f));
	scanf("%lld%lld%lld",&CCF,&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld%lld",&u,&uu,&bq1,&bq2);
		if(bq2==0)e[u].push_back(cyl(uu,bq1,bq2)),e[uu].push_back(cyl(u,bq1,bq2));
		else v[u].push_back(cyl(uu,bq1,bq2)),v[uu].push_back(cyl(u,bq1,bq2));
	}
	scanf("%lld%lld",&s,&t);
	f[0][s]=0;
	for(int i=0;i<CCF;i++){
		for(int j=1;j<=n;j++)
			if(f[0][0]!=f[i][j])rd[i][j]=1,q.push(j);
		while(!q.empty()){
			u=q.front();q.pop();rd[i][u]=0;
			for(cyl k:e[u])
				if(f[i][k.u]>f[i][u]+k.bq1){
					f[i][k.u]=f[i][u]+k.bq1;
					if(!rd[i][k.u])q.push(k.u),rd[i][k.u]=1;
				}
		}
		for(int j=1;j<=n;j++){
			for(cyl k:v[j])
				if(i+k.bq2<CCF)f[i+k.bq2][k.u]=min(f[i+k.bq2][k.u],f[i][j]+k.bq1);			
		}		
	}

	for(int i=0;i<CCF;i++)ans=min(ans,f[i][t]);
	return printf("%lld",((ans==0x3f3f3f3f)?-1:ans)),0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值