[ZJOI2006]物流运输
作者:互联网
一道典型的早期OI题目:数据范围小,技巧性不强,代码简短,考察的知识点比较初级,但客观上来说仍然具有一定的思维难度。
对于这道题来说,读懂题是关键。题目是说假如给定一张无向图,图上一些节点在某个时间段内无法使用,且知道每次改变路径都会付出一定代价,询问总花费最小值。
显然可以考虑DP。用f[i]代表第一天到第i天的最少花费,很显然这个状态设计具有无后效性,于是就可以考虑枚举决策。每个决策实际上对应的是一段时间内要求走同一条路径的最小花费,跑最短路即可。由于数据范围很小可以轻松过掉。
#include<cstdio>
#include<queue>
#include<cstring>
//#define zczc
#define int long long
using namespace std;
const int N=25;
const int M=110;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline int min(int s1,int s2){
return s1<s2?s1:s2;
}
int m,n,es,cost,f[M],sum[N][M];
struct edge{
int t,v,next;
}e[N*N*2];
int head[N],esum;
inline void add(int fr,int to,int val){
e[++esum]=(edge){to,val,head[fr]};head[fr]=esum;
}
int cnt,a[N],dis[N];
struct node{
int id,dis;
};
inline bool operator <(node s1,node s2){
return s2.dis<s1.dis;
}
priority_queue<node>q;
int c(int l,int r){
memset(dis,0x3f,sizeof(dis));
q.push((node){1,dis[1]=0});
while(!q.empty()){
node now=q.top();q.pop();
int wh=now.id,nd=now.dis;
if(sum[wh][r]-sum[wh][l-1]>0||nd>dis[wh])continue;
for(int i=head[wh],th;i;i=e[i].next){
if(dis[wh]+e[i].v<dis[th=e[i].t]){
dis[th]=dis[wh]+e[i].v;
q.push((node){th,dis[th]});
}
}
}
return min(dis[m],1e9);
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
int s1,s2,s3;
read(n);read(m);read(cost);read(es);
while(es--){
read(s1);read(s2);read(s3);
add(s1,s2,s3);add(s2,s1,s3);
}
read(es);
while(es--){
read(s1);read(s2);read(s3);
for(int i=s2;i<=s3;i++)sum[s1][i]=1;
}
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
sum[i][j]+=sum[i][j-1];
memset(f,0x3f,sizeof(f));
f[0]=-cost;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
f[i]=min(f[i],f[j-1]+c(j,i)*(i-j+1)+cost);
printf("%lld\n",f[n]);
return 0;
}
标签:运输,now,int,wh,物流,while,ZJOI2006,include,dis 来源: https://www.cnblogs.com/dai-se-can-tian/p/16290410.html