zoukankan      html  css  js  c++  java
  • poj 1201 Intervals(第一道差分约束题)

    呃,这是我做的第一道差分约束题,想先谈谈我对差分约束的理解,由于本人能力有限,可能理解有点浅显。如果您已看过相关讲解,请无视之。。。。

    1、想看的是百度百科和维基百科上对差分约束的的定义,上面都举了同一个例子,就是,寻找一个5个向量x=(xi)以满足下列8个差分约束条件:

    x1-x2≤0 ,x1-x5≤-1 ,x2-x5≤1 ,x3-x1≤5 ,x4-x1≤4 ,x4-x3≤-1 ,x5-x3≤-3 ,x5-x4≤-3

    然后讲了用Bellman_ford求最短路的方法来实现差分约束。

    2、然后,看了这道题,本以为会是一道裸的差分约束题,想了一会,很是没思路,很没“骨气”的查了解题报告,结果又了解了一点知识,那就是通过最短路径算法求出来的一组解当中,所有未知数都达到最大值,由此有查到了一篇讲差分约束很好的Blog,http://imlazy.ycool.com/post.1702305.html里面讲的很详细,而且也简单的证明了上面那句话,虽然没想出具体方法验证,但是他的讲解还是让我明白了这个结论。个人觉得这篇Blog让我受益最大。

    还有下面这个对这题的讲解最详细

    http://blog.csdn.net/morgan_xww/article/details/6359229

    但是http://blog.csdn.net/guzhilei1986/article/details/2305137做法更简单。

    下面说说这题吧。

    题意:给出N个区间以及每个区间对应的整数,计算一个有最小元素个数的集合,使得对于每个给出的区间,集合与它的相同元素个数不小于相应的整数。

    思路:呃, 首先要承认,这题的思路真不是自己的思路,参考了解题报告。假设,dis[i+1] 代表源点到xi 点的满足题目中要求的最少的点数,因此可以得出不等式dis[j] - dis[i-1] >= ci;

    即dis[j] >= dis[i-1] + ci,有这个不等式我们很容易想到单源最短路,但是上面说咯额,通过最短路方法求出的一组解中,所有未知数都达到最大值,题目中要求的是从s点到t点的最少数目的点,所以我们要改为求最长路,为什么要这样,可以参考第一Blog中的讲解。但是只有上面的不等式是不够得,题目中还有一个隐藏的要求, 即0<= dis[j+1] - dis[j] <= 1 ,由此可以求出满足要求的最少的点。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #define N  50005
    #define M 100000
    #define INF 0xffff
    using namespace std ;
    
    struct node
    {
        int s ;
        int e ;
        int val ;
    }p[N] ;
    
    int dis[M] ;
    int minn , maxx ;
    
    int Bellman_ford ( int n )
    {
        int i , j , flag ;
    
        for ( i = minn ; i <= maxx ; i++ )
        dis[i] = -INF;
        dis[minn] = 0 ;
    
        for ( i = 0 ; i <= maxx - minn ; i++ )
        {
            flag = 0 ;
            for ( j = 1 ; j <= n ; j++ )
            {
                if ( dis[p[j].s] != -INF && dis[p[j].s] + p[j].val > dis[p[j].e] )
                {
                    dis[p[j].e] = dis[p[j].s] + p[j].val ;
                    flag = 1 ;
                }
            }
            for ( j = minn ; j < maxx ; j++ )
            {
                if ( dis[j] != -INF && dis[j] > dis[j+1] )
                {
                    dis[j+1] = dis[j] ;
                    flag = 1 ;
                }
            }
            for ( j = maxx ; j > minn ; j-- )
            {
                if ( dis[j] != -INF && dis[j] - 1 > dis[j-1] )
                {
                    dis[j-1] = dis[j] - 1;
                    flag = 1 ;
                }
            }
            if ( !flag )
            break;
        }
        return dis[maxx] ;
    }
    
    int main()
    {
        int n , i ;
    
        while ( scanf ( "%d" , &n ) != EOF )
        {
            minn = INF ;
            maxx = -INF ;
            for ( i = 1 ; i <= n ; i++ )
            {
                scanf ( "%d%d%d" , &p[i].s , &p[i].e , &p[i].val );
                p[i].e++ ;
                if ( p[i].s < minn )
                minn = p[i].s ;
                if ( p[i].e > maxx )
                maxx = p[i].e ;
            }
            printf ( "%d\n" , Bellman_ford( n ));
        }
        return 0 ;
    }
  • 相关阅读:
    (转)批量导出存储过程
    (转)ylbtech-cnblogs(博客园)-数据库设计-6.0-Msg(短消息)
    (转)怎样玩转千万级别的数据
    (转)处理上百万条的数据库如何提高处理查询速度
    (转)SQLSERVER表分区的介绍(二)
    (转)SQLSERVER表分区的介绍(一)
    (转)在SQL中取出字符串中数字部分或在SQL中取出字符部分
    (转)SQL按照日、周、月、年统计数据
    构建操作mysql的类
    解决Celery 在Windows中搭建和使用的版本
  • 原文地址:https://www.cnblogs.com/misty1/p/2602112.html
Copyright © 2011-2022 走看看