zoukankan      html  css  js  c++  java
  • 2018.10.23-dtoj-1608新三国争霸(fight)

    题目描述:

    P 特别喜欢玩即时战略类游戏,但他觉得那些游戏都有美中不足的地方。灾害总不降临道路,而只降临城市,而且道路不能被占领,没有保护粮草的真实性。于是他就研发了《新三国争霸》。

    在这款游戏中,加入灾害对道路的影响(也就是一旦道路W[i,j]受到了灾害的影响,那么在一定时间内,这条路将不能通过)和道路的占领权(对于一条道路W[i,j],至少需要K[i,j]个士兵才能守住)。当灾难发生时,不能在发生灾难的道路驻扎士兵。

    PP可真是高手,不一会,就攻下了N-1座城市,加上原来的就有N座城市了,但他忽略了一点……那就是防守同样重要,不过现在还来的及。因为才打完仗所以很多城市都需要建设,PP估算了一下,大概需要T天。他现在无暇分身进攻了,只好在这T天内好好的搞建设了。所以他秒要派士兵占领一些道路,以确保任何两个城市之间都有路(不然敌人就要分而攻之了,是很危险的)。士兵可不是白干活的,每个士兵每天都要吃掉V的军粮。因为有灾害,所以方案可能有变化(每改变一次就需要K的军粮,初始方案也需要K的军粮)。

    因为游戏是PP编的,所以他知道什么时候有灾害。PP可是一个很节约的人,他希望这T天在道路的防守上花最少的军粮。

    输入:

    第一行有5个整数N,M,T,V,K。N表示有城市数,M表示道路数,T表示需要修养的天数,V表示每个士兵每天吃掉的军粮数,K表示修改一次花掉的军粮数。

    以下M行,每行3个数A,B,C。表示A与B有一条路(路是双向的)需要C个士兵才能守住。

    第M+2行是一个数P,表示有P个灾害。

    以下P行,每行4个数,X,Y,T1,T2。表示X到Y的这条路,在T1到T2这几天都会受灾害。

    输出:

    T天在道路的防守上花费最少的军粮。

    数据范围:

    N<=300,M<=5000 ,T<=50;

    v<=20,p<=10000,c<=300

    算法标签:DP,Kruskal

    思路:

    这题数据范围都不大,考虑用f[i]前i天完成道路防守所需的最少军粮。转移考虑枚举一个j表示在i-j天里没有改变过方案,于是得到f[i]=max(f[j]+v*(j-i)*get(j+1,i)+k);其中get(x,y)表示在x-y天内用的道路的最小权值,我们可以去掉在这几天里不可用的道路,跑kruskal最小生成树。效率是O(m*n2)

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=305,M=5003;const LL inf=1e15;int n,m,t,v,k,s[N][N][53],fa[N];LL f[N];struct node{int l,r,c;}tt[M];
    il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
    il int getfa(int x){if(fa[x]==x)return x;return fa[x]=getfa(fa[x]);}
    il bool cmp(node t1,node t2){return t1.c<t2.c;}
    il LL get(int a,int b){
        for(int i=1;i<=n;i++)fa[i]=i;int num=0;LL res=0;
        for(int i=1;i<=m;i++){
            if(s[tt[i].l][tt[i].r][b]-s[tt[i].l][tt[i].r][a-1]>0)continue;
            int x=getfa(tt[i].l),y=getfa(tt[i].r);
            if(x==y)continue;
            num++;res+=(LL)tt[i].c;if(num==n-1)break;fa[x]=y;
        }
        if(num==n-1)return res;return inf;
    }
    int main()
    {
        n=read();m=read();t=read();v=read();k=read();
        for(int i=1;i<=m;i++)tt[i].l=read(),tt[i].r=read(),tt[i].c=read();sort(tt+1,tt+1+m,cmp);
        int P=read();while(P--){
            int x=read(),y=read(),t1=read(),t2=read();
            for(int i=t1;i<=t2;i++)s[x][y][i]++,s[y][x][i]++;
        }
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=t;k++)s[i][j][k]+=s[i][j][k-1];
        for(int i=1;i<=t;i++)f[i]=inf;
        for(int i=1;i<=t;i++)for(int j=0;j<i;j++)
            f[i]=min(f[j]+(LL)(i-j)*(LL)v*get(j+1,i)+(LL)k,f[i]);
        printf("%lld
    ",f[t]);
      return 0;
    }
    View Code
  • 相关阅读:
    个推微服务网关架构实践
    NB-IoT 的“前世今生”
    个推基于Consul的配置管理
    个推Node.js 微服务实践:基于容器的一站式命令行工具链
    个推用户画像的实践与应用
    TensorFlow分布式实践
    个数是如何用大数据做行为预测的?
    QCon技术干货:个推基于Docker和Kubernetes的微服务实践
    基于CMS的组件复用实践
    数据可视化:浅谈热力图如何在前端实现
  • 原文地址:https://www.cnblogs.com/Jessie-/p/9838774.html
Copyright © 2011-2022 走看看