zl程序教程

您现在的位置是:首页 >  其它

当前栏目

POJ3614奶牛晒阳光DINIC或者贪心

或者 贪心 奶牛 阳光
2023-09-11 14:14:00 时间
题意:
      n个区间,m种点,每种点有ci个,如果一个点的范围在一个区间上,那么就可以消耗掉一个区间,问最多可以消耗多少个区间,就是这n个区间中,有多少个可能被抵消掉。


思路:
      方法不唯一,首先可以用贪心来做,看到网上说的都是优先队列的解法,我说下我的想法,我是直接sort排序后暴力(其实根本达不到n*m*l的时间复杂度),我先把所有老牛也就是区间按照上端点(***不是他们说的下端点)从小打到排序,然后在把护肤品按照第一个值从小到大排序,然后就是给给每一个护肤品尽可能找到一个点,同时这个点的右端点尽可能的小,为了后面别的护肤品留下更大的机会,下面分析枚举代码
第i个护肤品的第j个和第k只奶牛


for(i = 1 ;i <= m ;i ++)
for(j = 1 ;j <= sp[i].c ;j ++)
{
    for(k = 1 ;k <= n ;k ++)
    if(!mark[k] && cow[k].l <= sp[i].p && cow[k].r >= sp[i].p)
    {
          ans ++;
          mark[k] = 1;
          break;  
    }
    if(k == n + 1) 我个人觉得我加的这个地方可以很好的优化掉很多数据,这么加的
    break;         依据是如果第i种护肤品的第j个不能给剩下的奶牛用了,那么第i种
}                  的其他的也没用了,直接break




还有就是这个题目可以最大流来做,至于用那种算法,自己随意吧,我用的是DINC,建图比较简单,我不想说了,如果你做过流的话一下就能想到建图了,其实我感觉这个题目用最大流有点悬,但是AC了,因为边的条数可能达到 (2500*2500+5000)* 2 = 12510000。

贪心
#include<stdio.h>
#include<string.h>
#include<algorithm>

#define N 2500 + 10

using namespace std;

typedef struct
{
    int l ,r;
}COW;

typedef struct
{
    int p ,c;
}SP;

COW cow[N];
SP sp[N];
int mark[N];

bool camp1(COW a ,COW b)
{
    return  a.r < b.r;
}

bool camp2(SP a ,SP b)
{
    return a.p < b.p;
}

int main ()
{
    int n ,m, i ,j ,k;
    while(~scanf("%d %d" ,&n ,&m))
    {
        for(i = 1 ;i <= n ;i ++)
        scanf("%d %d" ,&cow[i].l ,&cow[i].r);
        for(i = 1 ;i <= m ;i ++)
        scanf("%d %d" ,&sp[i].p ,&sp[i].c);
        sort(cow + 1 ,cow + n + 1 ,camp1);
        sort(sp + 1 ,sp + m + 1 ,camp2);

        memset(mark ,0 ,sizeof(mark));
        int ans = 0;
        for(i = 1 ;i <= m ;i ++)
        for(j = 1 ;j <= sp[i].c ;j ++)
        {
            for(k = 1 ;k <= n ;k ++)
            if(!mark[k] && cow[k].l <= sp[i].p && cow[k].r >= sp[i].p)
            {
                ans ++;
                mark[k] = 1;
                break;
            }
            if(k == n + 1)
            break;
        }
        printf("%d\n" ,ans);
    }
    return 0;
}


DINIC

#include<queue>
#include<stdio.h>
#include<string.h>

#define N_node 2500 + 10
#define N_edge (2500 * 2500 + 5000) * 2 + 100
#define INF 1000000000

using namespace std;

typedef struct
{
    int to ,cost ,next;
}STAR;

typedef struct
{
    int x ,t;
}DEP;

typedef struct
{
    int l ,r;
}COW;

typedef struct
{
    int p ,c;
}SP;


COW cow[N_node];
SP sp[N_node];
STAR E[N_edge];
int list[N_node] ,list2[N_node] ,tot;
int deep[N_node];
DEP xin ,tou;

int minn(int x ,int y)
{
    return x < y ? x : y;
}

void add(int a ,int b ,int c)
{
    E[++tot].to = b;
    E[tot].cost = c;
    E[tot].next = list[a];
    list[a] = tot;

    E[++tot].to = a;
    E[tot].cost = 0;
    E[tot].next = list[b];
    list[b] = tot;
}

bool BFS_Deep(int s ,int t ,int n)
{
    memset(deep ,255 ,sizeof(deep));
    xin.x = s ,xin.t = 0;
    deep[xin.x] = xin.t;
    queue<DEP>q;
    q.push(xin);
    while(!q.empty())
    {
        tou = q.front();
        q.pop();
        for(int k = list[tou.x] ;k ;k = E[k].next)
        {
            int to = E[k].to;
            if(deep[to] != -1 || !E[k].cost)
            continue;
            xin.x = to ,xin.t = tou.t + 1;
            deep[xin.x] = xin.t;
            q.push(xin);
        }
    }
    for(int i = 0 ;i <= n ;i ++)
    list2[i] = list[i];
    return deep[t] != -1;
}

int DFS_Flow(int s ,int t ,int flow)
{
    if(s == t) return flow;
    int nowflow = 0;
    for(int k = list2[s] ;k ;k = E[k].next)
    {
        int to = E[k].to;
        int c = E[k].cost;
        list2[s] = k;
        if(deep[to] != deep[s] + 1 || !c)
        continue;
        int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
        nowflow += tmp;
        E[k].cost -= tmp;
        E[k^1].cost += tmp;
        if(flow == nowflow) break;
    }
    if(!nowflow) deep[s] = 0;
    return nowflow;
}

int DINIC(int s ,int t ,int n)
{
    int ans = 0;
    while(BFS_Deep(s ,t ,n))
    {
        ans += DFS_Flow(s ,t ,INF);
    }
    return ans;
}

int main ()
{
    int n ,m, i ,j;
    while(~scanf("%d %d" ,&n ,&m))
    {
        memset(list ,0 ,sizeof(list));
        tot = 1;
        for(i = 1 ;i <= n ;i ++)
        {
            scanf("%d %d" ,&cow[i].l ,&cow[i].r);
            add(0 ,i ,1);
        }
        for(i = 1 ;i <= m ;i ++)
        {
            scanf("%d %d" ,&sp[i].p ,&sp[i].c);
            add(i + n ,m + n + 1 ,sp[i].c);
        }

        for(i = 1 ;i <= n ;i ++)
        for(j = 1 ;j <= m ;j ++)
        if(cow[i].l <= sp[j].p && cow[i].r >= sp[j].p)
        add(i ,j + n ,1);

        printf("%d\n" ,DINIC(0 ,n + m + 1 ,n + m + 1));
    }
    return 0;

}