码迷,mamicode.com
首页 > 其他好文 > 详细

TYVJ1064 新三国争霸

时间:2014-11-05 16:53:17      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:io   os   for   sp   div   on   问题   bs   ad   

描述

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。

 思路:看到题,表示吓到了,一开始没有读懂,连样例都不知道怎么出来的。后来同组的dada以飞速ac,于是就向他求救了。大神就是大神,把边的信息存下来,用了个二维、三维的数组,然后就是dp部分了,穷举每一次不变安排的开始和终结点,注意j(起点)要从i-1到0,因为要对边的取得情况进行判断,用了flag数组和||运算。然后就是最小生成树求边权和的问题了,用的并查集的做法,很简单就能的出tt,最后f(i)=min(f(i),f(j)+tt*(i-j)*v+k)。

code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct uses{
 int st,en,va;
}tree[10000];
int road[500][500]={0},f[100],n,fa[500];
bool cn[500][500][100]={false},flag[500][500]={false};
int my_comp(const uses &x,const uses &y)
{
 if (x.va<y.va) return 1;
 return 0;
}
int root(int x)
{
 if (fa[x]!=x) fa[x]=root(fa[x]);
 return fa[x];
}
int main()
{
 int sum,m,t,v,k,i,j,a,b,c,x,y,t1,t2,p,tot=0,ans,r2,r1;
 cin>>n>>m>>t>>v>>k;
 memset(f,127,sizeof(f));
 for (i=1;i<=m;++i)
 {
  cin>>a>>b>>c;
  if (a>n||b>n) continue;
  road[a][b]=road[b][a]=c;
 }
 cin>>p;
 for (i=1;i<=p;++i)
 {
  cin>>x>>y>>t1>>t2;
  if (road[x][y]==0) continue;
  if (t1>t2) 
  {
   a=t1;t1=t2;t2=a;
  }
  if (t1>t) continue;
  if (t2>t) t2=t;
  for (j=t1;j<=t2;++j)
    cn[x][y][j]=cn[y][x][j]=true;
 }
 f[0]=0;tot=0;
 for (i=1;i<n;++i)
   for (j=i+1;j<=n;++j)
     if (road[i][j]>0)
     {
     ++tot;
     tree[tot].st=i;
     tree[tot].en=j;
     tree[tot].va=road[i][j];
    }
 sort(tree+1,tree+tot+1,my_comp);
 for (i=1;i<=t;++i)
 {
   memset(flag,false,sizeof(flag));
   for (j=i-1;j>=0;--j)
   {
    sum=1;
    ans=0;
    for (a=1;a<=n;++a)
      fa[a]=a;
  for (a=1;a<=tot;++a)
  {
    flag[tree[a].st][tree[a].en]=
      flag[tree[a].st][tree[a].en]||(cn[tree[a].st][tree[a].en][j+1]);
    if (!flag[tree[a].st][tree[a].en])
    {
   r1=root(tree[a].st);
      r2=root(tree[a].en);
      if (r1!=r2)
      { 
     fa[r1]=r2;
     ans=ans+tree[a].va;
     ++sum;
      } 
    }
    if (sum==n) break;
     }
     if (sum>=n)
  f[i]=min(f[i],f[j]+ans*(i-j)*v+k);
   }
    }
 cout<<f[t]<<endl;

TYVJ1064 新三国争霸

标签:io   os   for   sp   div   on   问题   bs   ad   

原文地址:http://www.cnblogs.com/Rivendell/p/4076455.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!