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;
}