1. 程式人生 > >codevs 1403 新三國爭霸

codevs 1403 新三國爭霸

用dp[i]表示第i天的最少花費
cost[i][j]表示從i到j天方案不變時的士兵數
用雙層迴圈+kruskal預處理出cost[i][j]

P[u][v][t]表示u到v的路在t時間是否可用 (即災害)
按照時間軸進行dp,外層迴圈i,內層迴圈j表示它的方案從第j天轉移而來
dp[i]=min(dp[i],dp[j]+cost[j+1][i]*V*(i-j));
即從第j天改變方案,選擇最小合法方案後,一直到第i天
初始化dp[i]=cost[1][i]*i*V; //注意cost[1][i]可能等於inf
最後dp[i]+=K;表示在某一天改變了一次方案

 

  1
#include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define re register 7 #define llint long long 8 #define wl putchar('\n') 9 #define read1(a) scanf("%d",&a) 10 #define De(a) cout<<a<<endl 11
using namespace std; 12 template <typename ty> inline void read(ty &x) 13 { 14 x=0;int f=1;re char c=getchar(); 15 for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=-1; 16 for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48); 17 x*=f; 18 }
19 template <typename ty> inline void write(ty x) 20 { 21 if(x<0) x=-x,putchar('-'); 22 if(x>9) write(x/10); 23 putchar(x%10+48); 24 } 25 const int inf = 0x3f3f3f3f; 26 struct edge{ 27 int u,v,c; 28 }e[5005<<1]; 29 int fa[5000]; 30 int cost[500][500],dp[500]; 31 inline bool cmp(edge a,edge b) 32 { 33 return a.c<b.c; 34 } 35 bool P[305][305][60]; 36 int N,M,T,V,K; 37 int q; 38 39 inline int find(int x) 40 { 41 return x==fa[x]?x:fa[x]=find(fa[x]); 42 } 43 bool check(int u,int v,int t1,int t2) 44 { 45 for(int i=t1;i<=t2;i++) 46 if(P[u][v][i]) return false; 47 return true; 48 } 49 inline int kruskal(int t1,int t2) 50 { 51 int cnt=1,ans=0; 52 for(int i=1;i<=N;i++) 53 fa[i]=i; 54 55 for(int i=1;i<=M;i++) 56 { 57 if(e[i].u==e[i].v) continue; 58 if(check(e[i].u,e[i].v,t1,t2)==0) continue; 59 int fx=find(e[i].u),fy=find(e[i].v); 60 61 if(fx==fy) continue; 62 63 ans+=e[i].c; 64 fa[fy]=fx; 65 cnt++;//在這裡數是否把所有的點都加入mst 66 if(cnt == N) break; 67 } 68 if(cnt==N) return ans; 69 return inf; 70 } 71 72 int main() 73 { 74 read(N),read(M),read(T),read(V),read(K); 75 for(re int i=1;i<=M;i++) 76 { 77 read(e[i].u),read(e[i].v),read(e[i].c); 78 } 79 sort(e+1,e+M+1,cmp); 80 read(q); 81 for(re int i=1;i<=q;i++) 82 { 83 int u,v,t1,t2; 84 read(u),read(v),read(t1),read(t2); 85 for(int j=t1;j<=t2;j++) 86 { 87 P[u][v][j]=P[v][u][j]=1;//uv路徑不可用 88 } 89 } 90 for(int i=1;i<=T;i++) 91 { 92 for(int j=i;j<=T;j++) 93 { 94 cost[i][j] = kruskal(i,j);//預處理從i到j天的mst 95 printf("%d ",cost[i][j]); 96 } 97 puts(""); 98 } 99 for(int i=1;i<=T;i++) 100 { 101 if(cost[1][i]!=inf) dp[i]=cost[1][i]*i*V;//表示初始化為一直用第一天開始的方案 102 else dp[i]=cost[1][i];//防止爆掉 103 for(int j=1;j<i;j++) 104 { 105 if(cost[j+1][i]!=inf)//若從j+1到i天存在mst 106 dp[i]=min(dp[i],dp[j]+cost[j+1][i]*V*(i-j));//cost[j+1][i]*V*(i-j)表示從j+1天到i天的花費 107 } 108 dp[i]+=K;//這裡加k,以後轉移的時候也會包含這個k 109 } 110 write(dp[T]); 111 } 112