DTOJ 1608 新三国争霸

xiaoxiao2022-06-11  28

1608: 新三国争霸(fight)

时间限制: 1 Sec  内存限制: 128 MB   提交: 117  解决: 47

题目描述

PP 特别喜欢玩即时战略类游戏,但他觉得那些游戏都有美中不足的地方。灾害总不降临道路,而只降临城市,而且道路不能被占领,没有保护粮草的真实性。于是他就研发了《新三国争霸》。

在这款游戏中,加入灾害对道路的影响(也就是一旦道路W[i,j]受到了灾害的影响,那么在一定时间内,这条路将不能通过)和道路的占领权(对于一条道路W[i,j],至少需要K[i,j]个士兵才能守住)。当灾难发生时,不能在发生灾难的道路驻扎士兵。

PP可真是高手,不一会,就攻下了N-1座城市,加上原来的就有N座城市了,但他忽略了一点……那就是防守同样重要,不过现在还来的及。因为才打完仗所以很多城市都需要建设,PP估算了一下,大概需要T天。他现在无暇分身进攻了,只好在这T天内好好的搞建设了。所以他秒要派士兵占领一些道路,以确保任何两个城市之间都有路(不然敌人就要分而攻之了,是很危险的)。士兵可不是白干活的,每个士兵每天都要吃掉V的军粮。因为有灾害,所以方案可能有变化(每改变一次就需要K的军粮,初始方案也需要K的军粮)。

因为游戏是PP编的,所以他知道什么时候有灾害。PP可是一个很节约的人,他希望这T天在道路的防守上花最少的军粮。

N<=300,M<=5000 ,T<=50;

v<=20,p<=10000,c<=300

 

输入

第一行有5个整数N,M,T,V,K。N表示有城市数,M表示道路数,T表示需要修养的天数,V表示每个士兵每天吃掉的军粮数,K表示修改一次花掉的军粮数。

以下M行,每行3个数A,B,C。表示A与B有一条路(路是双向的)需要C个士兵才能守住。

第M+2行是一个数P,表示有P个灾害。

以下P行,每行4个数,X,Y,T1,T2。表示X到Y的这条路,在T1到T2这几天都会受灾害。

 

输出

T天在道路的防守上花费最少的军粮。

 

题解:

考虑DP。

设表示前个时刻,所需要的最小花费。

那么,考虑转移:

表示你在强制变化方案。

考虑这个 ,我们可以用求出在这段区间里均可以使用的边集中产生的最小生成树。

 

#include<bits/stdc++.h> using namespace std; #define in inline #define re register #define rep(i,a,b) for(re int i=a;i<=b;i++) #define repd(i,a,b) for(re int i=a;i>=b;i++) #define For(i,a,b) for(int i=a;i<b;i++) #define _(d) while(d(isdigit(ch=getchar()))) template<class T>in void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;} typedef long long ll; const int N=1e4+4,M=504; int n,m,t,V,k,p; struct EE{int u,v;ll w;}ee[N]; int e[M][M],tp,vis[N];ll f[N]; typedef pair<int,int>P; vector<P>v[M][M]; bool cmp(EE a,EE b){return a.w<b.w;} int fa[N]; #define mk(a,b) make_pair(a,b) #define fi first #define se second vector<P>::iterator it ; in int F(int x){return fa[x]==x?x:fa[x]=F(fa[x]);} in ll work(int l,int r){ rep(i,1,m) vis[i]=0; rep(i,1,m){ int x=ee[i].u,y=ee[i].v; if(v[x][y].empty()) continue; for(it=v[x][y].begin();it!=v[x][y].end();it++){ P tmp=*it; int L=tmp.fi,R=tmp.se; if(L>R) swap(L,R); if((L>=l&&L<=r)||(R>=l&&R<=r)||(L<=l&&R>=r)){vis[i]=1;break;} } } rep(i,1,n) fa[i]=i; int num=0;ll sum=0; rep(i,1,m){ if(vis[i]) continue; int x=ee[i].u,y=ee[i].v; x=F(x),y=F(y); if(x!=y) fa[x]=y,sum+=ee[i].w,num++; if(num==n-1) break; } if(num==n-1) return sum; return 0; } int main(){ g(n),g(m),g(t),g(V),g(k); rep(i,1,m) g(ee[i].u),g(ee[i].v),g(ee[i].w); sort(ee+1,ee+1+m,cmp);g(p); rep(i,1,p){ int x,y,t1,t2;g(x),g(y),g(t1),g(t2); if(t1>t2) swap(t1,t2); v[x][y].push_back(mk(t1,t2)); v[y][x].push_back(mk(t1,t2)); } rep(i,1,t) f[i]=1e17; rep(i,1,t){ For(j,0,i){ int tmp=work(j+1,i); if(tmp) f[i]=min(f[i],f[j]+1ll*(i-j)*V*tmp+k); } } return !printf("%lld",f[t]); }

 

转载请注明原文地址: https://www.6miu.com/read-4930283.html

最新回复(0)