1. 程式人生 > >POJ3614奶牛晒陽光DINIC或者貪心

POJ3614奶牛晒陽光DINIC或者貪心

題意:
      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;

}