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  

原文地址:https://www.cnblogs.com/tythen/p/10052382.html

时间: 2024-10-20 08:57:09

codevs 1403 新三国争霸的相关文章

codevs1403 新三国争霸

题目描述 Description PP 特别喜欢玩即时战略类游戏,但他觉得那些游戏都有美中不足的地方.灾害总不降临道路,而只降临城市,而且道路不能被占领,没有保护粮草的真实性.于是他就研发了<新三国争霸>.在这款游戏中,加入灾害对道路的影响(也就是一旦道路W[i,j]受到了灾害的影响,那么在一定时间内,这条路将不能通过)和道路的占领权(对于一条道路W[i,j],至少需要K[i,j]个士兵才能守住).PP可真是高手,不一会,就攻下了N-1座城市,加上原来的就有N座城市了,但他忽略了一点……那就是

TYVJ1064 新三国争霸

描述 PP 特别喜欢玩即时战略类游戏,但他觉得那些游戏都有美中不足的地方.灾害总不降临道路,而只降临城市,而且道路不能被占领,没有保护粮草的真实性.于是他就研发了<新三国争霸>.在这款游戏中,加入灾害对道路的影响(也就是一旦道路W[i,j]受到了灾害的影响,那么在一定时间内,这条路将不能通过)和道路的占领权(对于一条道路W[i,j],至少需要K[i,j]个士兵才能守住).PP可真是高手,不一会,就攻下了N-1座城市,加上原来的就有N座城市了,但他忽略了一点……那就是防守同样重要,不过现在还来的

[Codevs1403]新三国争霸(MST+DP)

题目:http://codevs.cn/problem/1403/ 分析: 很容易想到对于某个确定的一天,就是求个最小生成树,又因为数据范围很小,所以可以暴力.但问题的关键是如果相邻两天的方案不同,就要多付钱.这个问题很像bzoj1003. 考虑DP 设w[i][j]表示i~j天不换方案的最小花费,f[i]表示前i天总的最小花费,于是就枚举改变方案在哪一天 f[i]=min(f[i],f[j]+k+w[j+1][i]*v*(i-j))

Codevs 3324 新斯诺克

时间限制: 1 s  空间限制: 64000 KB  题目等级 : 白银 Silver 题目描述 Description 现在考虑这样一种新斯诺克,设母球(母球即是白球,用于击打其他球)的标号为M,台面上有N 个红球排成一排,每一个红球都有一个标号,他们的标号代表了他们的分数. 现在用母球击打这些红球,一杆击打,如果母球接触到红球,就称为“K 到红球”.我们假设,一次可以击打任意多相邻连续的红球,也可以只击打一个球.并且红球既不会落袋,也不会相互发生碰撞,而只是停留在原处.每次击打时候,要想“K

7、8月刷题总结

准备开学了囧,7.8月刷题记录,以后好来复习,并且还要好好总结! 数据结构: splay: [BZOJ]1503: [NOI2004]郁闷的出纳员(Splay) [BZOJ]1269: [AHOI2006]文本编辑器editor(Splay) [BZOJ]1507: [NOI2003]Editor(Splay) treap: [BZOJ]1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心) [BZOJ]3224: Tyvj

小结:动态规划

概要: 状态.转移:最优子结构.无后效性. 技巧及注意: dp就是纯经验+智商题 在dp方程写出来后,一定要考虑边界!不要以为转移对了就行了! 滚动数组的话一定要考虑好顺序! 下标有时候可以灵活使用!比如mod意义下的dp,倍数什么.可到达性等题目都可以这样做. 如果是线性序列的max{f[k]},k<i这种可以用线段树或bit维护成log 注意“前i”和“第i”的区别(特别对于答案更新),有时换一种就能解答出问题. 在状态加限制条件,如单调.地址等. 用下标来维护下标这个答案是否可达. 博弈论

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

【文学文娱】斗胆聊聊那《三国》

本文地址:http://www.cnblogs.com/aiweixiao/p/6985398.html 原文地址(微信):http://t.cn/RSmz9xs 点击关注微信公众号 三国·滚滚长江东逝水 这里说的<三国>,主要指的就是明朝罗贯中老先生的<三国演义>,当然出名的还有新旧两部<三国演义>的电视剧.我都很喜欢.<三国>的故事家喻户晓,里面的学问也是大了去了,文臣武将,兵法韬略,那个拿出来都能说上半天.大家也都有自己心目中的三国和三国英雄及故事.我

手机CPU

说起手机CPU的历史,笔者给大家提一个问题:"世界上第一款智能手机是什么呢?"相信很多人的答案是爱立信的R380或诺基亚的7650,但都不对,真正的首款智能手机是由摩托罗拉在2000年生产的名为天拓A6188的手机,它是全球第一部具有触摸屏的PDA手机,它同时也是第一部中文手写识别输入的手机,但最重要的是A6188采用了摩托罗拉公司自主研发的龙珠(Dragon ball EZ)16MHzCPU,支持WAP1.1无线上网,采用了PPSM (Personal Portable System