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 ;
    }
  • 相关阅读:
    洛谷 P1194 飞扬的小鸟 题解
    洛谷 P1197 星球大战 题解
    洛谷 P1879 玉米田Corn Fields 题解
    洛谷 P2796 Facer的程序 题解
    洛谷 P2398 GCD SUM 题解
    洛谷 P2051 中国象棋 题解
    洛谷 P1472 奶牛家谱 Cow Pedigrees 题解
    洛谷 P1004 方格取数 题解
    洛谷 P2331 最大子矩阵 题解
    洛谷 P1073 最优贸易 题解
  • 原文地址:https://www.cnblogs.com/misty1/p/2602112.html
Copyright © 2011-2022 走看看