TYVJ P1064 新三国争霸

题目:

http://www.tyvj.cn/Problem_Show.asp?id=1064

  TYVJ格式问题,这里不贴题了。

题解:

  一道非常不错的DP~~~~~~

  f[i]=min(f[j]+(i-j)*v*get(j+1,i)+k)(0<=j<i),用f[i]表示到第i天的最小费用为多少,则转移方程表示在第j+1天到第i天方案不变的费用。get(a,b)表示从第a天到第b天方案保持不变最小需要多少人,这个问题可以先排除不可用边后求最小生成树得到所需的值。枚举i,j,每次再做一次做小生成树,最终复杂度可以变为O(n*n*m)(在一开始时排一次序即可不用每次对选出的边排序,当然是用克鲁斯卡尔,虽然我的程序没有使用这个优化)

  题不难,但非常不错~~~~~~

View Code
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 const int maxn=601;
 9 const int maxm=10001;
10 const int maxt=100;
11 
12 long long f[maxt];
13 
14 int x[maxm],y[maxm],z[maxm],fa[maxn],p,n,m,v,k,dt1[maxm],dt2[maxm],ds[maxm],de[maxm],t;
15 
16 bool able[maxn][maxn];
17 
18 struct edge
19 {
20     int s,e,v;
21     bool operator<(const edge &a)const
22     {
23         return v<a.v;
24     }
25 }ed[maxm];
26 
27 int getf(int now)
28 {
29     if (now==fa[now]) return now;
30     else return fa[now]=getf(fa[now]);
31 }
32 
33 long long get(int t1,int t2)
34 {
35     memset(able,false,sizeof(able));
36     for (int a=1;a<=p;a++)
37         if (((dt1[a]<=t2) && (t1<=dt1[a])) || ((dt2[a]<=t2) && (t1<=dt2[a])) || ((t1>=dt1[a]) && (t1<=dt2[a])) || ((t2>=dt1[a]) && (t2<=dt2[a]))) able[ds[a]][de[a]]=able[de[a]][ds[a]]=true;
38     int ll=0;
39     for (int a=1;a<=m;a++)
40         if (!able[x[a]][y[a]])
41         {
42             ll++;
43             ed[ll].s=x[a];
44             ed[ll].e=y[a];
45             ed[ll].v=z[a];
46         }
47     sort(ed+1,ed+ll+1);
48     for (int a=1;a<=n;a++)
49         fa[a]=a;
50     int add=0;
51     long long nowans=0;
52     for (int a=1;a<=ll;a++)
53     {
54         int f1=getf(ed[a].s);
55         int f2=getf(ed[a].e);
56         if (f1!=f2)
57         {
58             add++;
59             fa[f1]=f2;
60             nowans+=ed[a].v;
61         }
62     }
63     if (add!=n-1) return f[t+1];
64     else return nowans;
65 }
66 
67 int main()
68 {
69     scanf("%d%d%d%d%d",&n,&m,&t,&v,&k);
70     for (int a=1;a<=m;a++)
71         scanf("%d%d%d",&x[a],&y[a],&z[a]);
72     scanf("%d",&p);
73     for (int a=1;a<=p;a++)
74         scanf("%d%d%d%d",&ds[a],&de[a],&dt1[a],&dt2[a]);
75     for (int a=1;a<=t+1;a++)
76         f[a]=123456789123456ll;
77     f[0]=0;
78     for (int a=1;a<=t;a++)
79         for (int b=0;b<a;b++)
80             f[a]=min(f[a],k+((long long)(v*(a-b)))*get(b+1,a)+f[b]);
81     printf("%I64d\n",f[t]);
82 
83     return 0;
84 }
原文地址:https://www.cnblogs.com/zhonghaoxi/p/2583557.html