• POJ 1716 Integer Intervals


    题意:给出一些区间,求一个集合的长度要求每个区间里都至少有两个集合里的数。

    解法:贪心或者差分约束。贪心的思路很简单,只要将区间按右边界排序,如果集合里最后两个元素都不在当前区间内,就把这个区间内的最后两个数加入集合,如果只有一个元素在区间里就加一个,如果两个元素都在区间里就不加。

    差分约束系统用来解一个不等式组,只要这个不等式组里的不等式形如x1 - x2 <= c,c为常数就可以用差分约束来解不等式,将每个变量看做点,每个不等式看做边,求一个最短路,那么dis[i]就是不等式的一组解,主要利用的原理就是在最短路问题中:dis[v] <= dis[u] + edge[u][v],而将x1 - x2 <= c进行移项就可以得到以上形式,由于有负权,所以一般用bellmanford或者spfa……不过我不会写spfa……如果产生负环说明无解。

    对于本题来说,将每个区间端点都看做点,sum[i]表示集合中小于等于i的数的个数,则对于一个区间[l, r]来说有不等式sum[r] - sum[l - 1] >= 2,转化成上述形式就是sum[l - 1] - sum[r] <= -2,可以看做是点r到点l-1的一条权值为-2的边。除了题中给出的条件,还有一个隐含条件为0 <= sum[i] - sum[i - 1] <= 1,用以上不等式建图后跑最短路,dis[n] - dis[0]即为答案。

    差分约束比较复杂……但是主要想练差分约束才做的这题= =但是数据范围略大……跑bellmanford有点难……最后1000ms擦边过的……

    代码:

    贪心:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #include<iomanip>
    #define LL long long
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    
    using namespace std;
    
    struct node
    {
        int l, r;
        bool operator < (const node &tmp) const
        {
            if(r == tmp.r) return l < tmp.l;
            return r < tmp.r;
        }
    }interval[10005];
    int main()
    {
        int n;
        while(~scanf("%d", &n))
        {
            for(int i = 0; i < n; i++)
                scanf("%d%d", &interval[i].l, &interval[i].r);
            sort(interval, interval + n);
            int x = -1, y = -1;
            int ans = 0;
            for(int i = 0; i < n; i++)
            {
                if(interval[i].l <= x) continue;
                if(interval[i].l <= y)
                {
                    x = y;
                    y = interval[i].r;
                    ans++;
                    continue;
                }
                x = interval[i].r - 1;
                y = interval[i].r;
                ans += 2;
            }
            cout << ans << endl;
        }
        return 0;
    }
    

      

    差分约束系统:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #include<iomanip>
    #define LL long long
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    
    using namespace std;
    
    struct node
    {
        int u, v, value;
        node(int u, int v, int value) : u(u), v(v), value(value) {}
        node() {}
    }edge[30005];
    int minn = 10000000, maxn, m, cnt;
    int dis[10005];
    const int inf = 0x3f3f3f3f;
    void BellmanFord()//由于不存在无解的数据,不需要判负环
    {
        memset(dis, 0, sizeof dis);
        dis[minn] = 0;
        bool flag = true;
        while(flag)//剪枝,如果本次没有进行松弛,则停止松弛
        {
            flag = false;
            for(int j = 0; j < cnt; j++)
                if(dis[edge[j].v] > dis[edge[j].u] + edge[j].value)
                {
                    flag = true;
                    dis[edge[j].v] = dis[edge[j].u] + edge[j].value;
                }
        }
    }
    int main()
    {
        while(~scanf("%d", &m))
        {
            cnt = 0;
            for(int i = 0; i < m; i++)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                minn = min(minn, min(a, b + 1));//记录最小点
                maxn = max(maxn, max(a, b + 1));//记录最大点
                edge[cnt++] = node(b + 1, a, -2);
            }
            for(int i = minn + 1; i <= maxn; i++)
            {
                edge[cnt++] = node(i - 1, i, 1);
                edge[cnt++] = node(i, i - 1, 0);
            }
            BellmanFord();
            cout << dis[maxn] - dis[minn] << endl;
        }
        return 0;
    }
    

      

  • 相关阅读:
    C#、Java实现按字节截取字符串包含中文汉字和英文字符数字标点符号等
    百度编辑器(UEditor)自定义工具栏
    ASP.NET使用百度编辑器(UEditor)使用方法
    C#设计模式--桥接模式
    C#设计模式--外观模式
    Entity Framework6测试使用
    Entity Framework6的在线下载安装
    C#设计模式--代理模式
    php 回调函数结合闭包(匿名函数)的使用示例
    函数的可变参数实例
  • 原文地址:https://www.cnblogs.com/Apro/p/4882064.html
Copyright © 2020-2023  润新知