填坑……链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1003
题意:每个点会动态开关,改变路程有一定开销,求出最小开销。
刚开始犯憷,后来发现$n$、$m$看反……瞬间变水题……
首先我们读入时便可以得出每一段时间内一个点是否开闭,于是我们就动态求出每一个时间区间内的最短路。
求出来之后,我们便可以偷税愉悦地$dp$了。设$f[i]$为到了第$i$天为止的最小花费,转移方程就是:$f[i]=min{f[j]+dis[j][i]*(i-j)+k}$,其中,$dis[j][i]$就是这$i-j$天全可以走的最短路长度。最后结果是$f[n]-k$。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=105,maxm=25; 7 int date[maxn][maxn],n,m,k,e;long long f[maxn],dis[maxn][maxn]; 8 struct node 9 { 10 int from,to,dis,next; 11 }edge[(maxn*maxn)<<1]; 12 int head[maxn],tot; 13 void addedge(int u,int v,int w) 14 { 15 edge[++tot]=(node){u,v,w,head[u]};head[u]=tot; 16 } 17 #include<queue> 18 int d[maxn];bool inqueue[maxn]; 19 queue<int>q; 20 void spfa(int l,int r) 21 { 22 for(int i=1;i<=m;i++)d[i]=100000000; 23 d[1]=0;inqueue[1]=1;q.push(1); 24 while(!q.empty()) 25 { 26 int s=q.front();q.pop();inqueue[s]=0; 27 for(int i=head[s];i;i=edge[i].next) 28 { 29 int v=edge[i].to; 30 if(date[v][r]-date[v][l-1]==0&&d[v]>d[s]+edge[i].dis) 31 { 32 d[v]=d[s]+edge[i].dis; 33 if(!inqueue[v]) 34 { 35 inqueue[v]=1; 36 q.push(v); 37 } 38 } 39 } 40 } 41 dis[l][r]=d[m]; 42 } 43 int haha() 44 { 45 scanf("%d%d%d%d",&n,&m,&k,&e); 46 for(int i=1;i<=e;i++) 47 { 48 int x,y,z;scanf("%d%d%d",&x,&y,&z); 49 addedge(x,y,z);addedge(y,x,z); 50 } 51 int d;scanf("%d",&d); 52 while(d--) 53 { 54 int x,l,r;scanf("%d%d%d",&x,&l,&r); 55 for(int i=l;i<=r;i++)date[x][i]++; 56 } 57 for(int i=1;i<=m;i++) 58 for(int j=1;j<=n;j++)date[i][j]+=date[i][j-1]; 59 for(int i=1;i<=n;i++) 60 for(int j=i;j<=n;j++)spfa(i,j); 61 for(int i=1;i<=n;i++) 62 { 63 f[i]=(long long)dis[1][i]*i; 64 for(int j=1;j<=i;j++)f[i]=min(f[i],f[j-1]+dis[j][i]*(i-j+1)+k); 65 } 66 printf("%lld ",f[n]); 67 } 68 int sb=haha(); 69 int main(){;}