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  

 

posted @ 2018-12-02 10:33  tythen  阅读(157)  评论(0编辑  收藏  举报