工程规划(答案错误)

【问题描述】

    造一幢大楼是一项艰巨的工程,它是由n个子任务构成的,给它们分别编号1,2,…,n(5≤n≤1000)。由于对一些任务的起始条件有着严格的限制,所以每个任务的起始时间T1,T2,…,Tn并不是很容易确定的(但这些起始时间都是非负整数,因为它们必须在整个工程开始后启动)。例如:挖掘完成后,紧接着就要打地基;但是混凝土浇筑完成后,却要等待一段时间再去掉模板。

    这种要求就可以用M(5≤m≤5000)个不等式表示,不等式形如Ti-Tj≤b代表i和j的起始时间必须满足的条件。每个不等式的右边都是一个常数b,这些常数可能不相同,但是它们都在区间(-100,100)内。

    你的任务就是写一个程序,给定像上面那样的不等式,找出一种可能的起始时间序列T1,T2,…,Tn,或者判断问题无解。对于有解的情况,要使最早进行的那个任务和整个工程的起始时间相同,也就是说,T1,T2,…,Tn中至少有一个为0。

【输入】

    第一行是用空格隔开的两个正整数n和m,下面的m行每行有三个用空格隔开的整数i,j,b对应着不等式Ti-Tj≤b。

【输出】

       如果有可行的方案,那么输出N行,每行都有一个非负整数且至少有一个为0,按顺序表示每个任务的起始时间。如果没有可行的方案,就输出信息“NO SOLUTION”。

【样例1

       work.in                               work.out

       5 8                                     0

       1 2 0                                  2

       1 5 –1                                5

       2 5 1                                  4

       3 1 5                                  1

       4 1 4

       4 3 –1

       5 3 –1

       5 4 –3

【样例2

       work.in                               work.out

       5 5                                     NO SOLUTION

       1 2 –3

       1 5 –1

       2 5 –1

       5 1 –5

       4 1 4

【算法分析】

       本题是一类称为约束满足问题的典型问题,问题描述成n个子任务的起始时间Ti及它们之间在取值上的约束,求一种满足所有约束的取值方法。

       将工程的n个子任务1,2,…,n作为一有向图G的n个顶点,顶点Vi(i=1,…,n)的关键值为子任务i的起始时间Ti,我们并不需要关心顶点之间的弧及其弧长,而是要确定顶点的关键值Ti的取值,满足所有的约束条件。本题的约束条件由m个不等式Ti-Tj≤b给出,这样的有向图称为约束图。

    为了确定每一个Ti的值,先假设某一个子任务的起始时间为零,如设Tj=0,则其余子任务的起始时间Ti相对于T1可设置其起始时间为一区间[-maxt,maxt]。

    下面分析不等式Ti-Tj≤b。此不等式可变形为如下两种形式:

    (1)Ti≤Tj+b意味Ti的最大值为Tj+b;

    (2)Tj≥Ti-b意味Tj的最大值为Ti-b;

    因此,根据题中给出的m个不等式,逐步调整各个Ti的最小值和最大值。

    设high[i]为Ti当前的最大值,low[i]为Ti当前的最小值。

    high[j]为Tj当前的最大值,low[j]为Tj当前的最小值。

    若high[i]-high[j]>b,则high[i]=high[j]+b(根据Ti≤Tj+b),

    若low[i]-low[j]<b,则low[j]=low[i]-b(根据Ti≥Ti-b)。

    以上的调整终止视下列两种情况而定:

    (1)对所有的不等式Ti-Tj≤b,不再有high[i]或low[j]的调整;

    (2)若存在high[i]<low[i]或high[j]<low[j]则表示不存在T1,T2,…,Tn能满足所有m个不等式Ti-Tj≤b,即问题无解。

/*
  <1>根据题意,假设一个开始任务,开始时间为0,其余的各项任务均
  维护一个时间范围,即low[i]—high[i]。 
  由 Ti-Tj<=b 得:① Ti<=Tj+b,即 high[i]=high[j]+b;
                 ② Tj>=Ti-b,即 low[j]=low[i]-b;
  <2>当high[i]-high[j]<=b 或者 low[i]-low[j]<=b 时,成立;
  反之,则用以上①②式更新。
  <3>当high[]<low[]时,没有可行方案,
  <4>当数据不再更新时,得出可行方案(满足数据非负,且至少有一个0)。 
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#define M 1010
#define N 5010
#define INF 10000
using namespace std;
int high[M],low[M];
struct node
{
    int x,y,v;
};node a[N];
int main()
{
    int n,m,x,y,v;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&v);
        a[i].x=x;
        a[i].y=y;
        a[i].v=v;
    }
    for(int i=2;i<=n;i++)
    {
        high[i]=INF;
        low[i]=-INF;
    }
    int flag=1,ff=0;
    while(flag)
    {
        flag=0;
        for(int i=1;i<=m;i++)
        {
            int x=a[i].x,y=a[i].y,b=a[i].v;
            if(high[x]-high[y]>b)
            {
                high[x]=high[y]+b;
                flag=1;
            }
            if(low[x]-low[y]>b)
            {
                low[y]=low[x]-b;
                flag=1;
            }
            if(high[x]<low[x]||high[y]<low[y])
            {
                ff=1;
                flag=0;
            }
        }
    }
    if(ff)printf("NO SOLUTION");
    else
    {
        int minn=INF;
        for(int i=1;i<=n;i++)
          minn=min(high[i],minn);
        for(int i=1;i<=n;i++)
          printf("%d\n",high[i]-minn);
    }
    return 0;
}
View Code

 

posted @ 2016-06-18 20:34  karles~  阅读(319)  评论(0编辑  收藏  举报