zoukankan      html  css  js  c++  java
  • zoj 2770 Burn the Linked Camp 差分约束系统

    题目大意:

    大家都知道,三国时期,蜀国刘备被吴国大都督陆逊打败了。刘备失败的原因是因为刘备的错误决策。他把部队分成几十个大营,每个大营驻扎一队部队,又用树木编成栅栏,把大营连成一片,称为连营。
    让我们回到那个时代。陆逊派了很多密探,获得了他的敌人-刘备的信息。通过密探,他知道刘备的部队已经分成几十个大营,这些大营连成一片(一字排开),这些大营从左到右用1...n编号。第i个大营最多能容纳Ci个士兵。而且通过观察刘备军队的动静,陆逊可以估计到从第i个大营到第j个大营至少有多少士兵。最后,陆逊必须估计出刘备最少有多少士兵,这样他才知道要派多少士兵去烧刘备的大营。
    为陆逊估计出刘备军队至少有多少士兵。然而,陆逊的估计可能不是很精确,如果不能很精确地估计出来,输出"Bad Estimations"

     

    对于样例数据:

    数学模型为:设3个军营的人数分别为A1, A2, A3,容量为C1, C2, C3,前n个军营的总人数为Sn,则有:

    1. 则根据第i个大营到第j个大营士兵总数至少有k个,得不等式组(1):
    S2 – S0 >= 1100 等价于 S0 – S2 <= -1100
    S3 – S1 >= 1300 等价于 S1 – S3 <= -1300

    2. 又根据实际情况,第i个大营到第j个大营的士兵总数不超过这些兵营容量之和,设d[i]为前i个大营容量总和,得不等式组(2):
    S2 – S0 <= d[2] – d[0] = 3000
    S3 – S1 <= d[3] – d[1] = 3000

    3. 每个兵营实际人数不超过容量,得不等式组(3)
    A1 <= 1000 等价于 S1 – S0 <= 1000
    A2 <= 2000 等价于 S2 – S1 <= 2000
    A3 <= 1000 等价于 S3 – S2 <= 1000

    4. 另外由Ai>=0,又得到不等式组(4)
    S0 – S1 <= 0
    S1 – S2 <= 0
    S2 – S3 <= 0
    求A1+A2+A3的最小值(即S3 – S0的最小值)

    构造好网络之后,最终要求什么?
    要求S3 – S0的最小值,即要求不等式:
    S3 – S0 >= M
    中的M,转化成:
    S0 – S3 <= -M
    即求S3到S0的最短路径,长度为-M
    求得-M为-1300,即M为1300

    #include <stdio.h>
    #define INF 9999999
    int n,m,dist[1010],c[1010],d[1010],ei;
    struct eg
    {
    	int u,v,w;
    }edges[23000];
    void init()
    {
    	ei=0;
    	int i;
    	for(i=0;i<=n;i++)
    		dist[i]=INF;
    	d[0]=0;
    	dist[n]=0;
    }
    bool bell()
    {
    	int i,k,t;
    	for(i=0;i<n;i++)
    	{
    		for(k=0;k<ei;k++)
    		{
    			t=dist[edges[k].u]+edges[k].w;
    			if(dist[edges[k].u]!=INF&&t<dist[edges[k].v])
    				dist[edges[k].v]=t;
    		}
    	}
    	for(k=0;k<ei;k++)
    	{
    		if(dist[edges[k].u]!=INF&&dist[edges[k].u]+edges[k].w<dist[edges[k].v])
    			return false;
    	}
    	return true;
    }
    int main()
    {
    	while(scanf("%d%d",&n,&m)!=EOF)
    	{
    		init();
    		int i,u,v,w;
    		for(i=1;i<=n;i++)
    		{
    			scanf("%d",&c[i]);
    			edges[ei].u=i-1;
    			edges[ei].v=i;
    			edges[ei].w=c[i];
    			ei++;
    			edges[ei].u=i;
    			edges[ei].v=i-1;
    			edges[ei].w=0;
    			ei++;
    			d[i]=c[i]+d[i-1];
    		}
    		for(i=0;i<m;i++)
    		{
    			scanf("%d%d%d",&u,&v,&w);
    			edges[ei].u=v;
    			edges[ei].v=u-1;
    			edges[ei].w=-w;
    			ei++;
    			edges[ei].u=u-1;
    			edges[ei].v=v;
    			edges[ei].w=d[v]-d[u-1];
    			ei++;
    		}
    		if(!bell())
    			printf("Bad Estimations
    ");
    		else printf("%d
    ",-dist[0]);
    	}
    	return 0;
    }
    


     


     

     

     

  • 相关阅读:
    汇编语言 第三章 寄存器
    汇编语言 第二章
    实验一 查看CPU和内存,用机器指令和汇编指令教程
    nginx的log、upstream和server
    高并发情况下Linux系统及kernel参数优化
    二进制方式安装docker(非root用户启动docker)
    redis
    redis配置文件详解
    Keepalived+LVS实现LNMP网站的高可用部署
    Nginx location相关配置说明
  • 原文地址:https://www.cnblogs.com/vermouth/p/3710217.html
Copyright © 2011-2022 走看看