现在的位置: 首页 > 综合 > 正文

线性规划与网络流24题 10-餐巾计划问题

2017年04月27日 ⁄ 综合 ⁄ 共 1705字 ⁄ 字号 评论关闭
把每天拆成两个点,需要用的餐巾数和用了的餐巾数,分别连源和汇,流量day[i],费用0
再从源点每天用的餐巾点,费用为p,流量无穷。
每天需要用的餐巾连下一天需要用的(没洗的),流量无穷,费用0;
每天用完的连n和m天后的用了的餐巾,费用f,s,流量无穷
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 100000000;
const static int V = 2010;
const static int E = 400000;
int sink, source, dis[V], pre[V];
bool vst[V];
int day[V];
struct Edge
{
    int v, flow, cost;
    Edge *next;
}pool[E], *adj[V],*pree[V],*pp;
void create(int u, int v, int flow, int cost)
{
    pp->flow = flow;
    pp->v = v;
    pp->cost = cost;
    pp->next = adj[u];
    adj[u] = pp++;
}
void addedge(int u, int v, int flow, int cost)
{
    //printf("%d %d %d %d\n",u,v,flow,cost);
    create(u,v,flow,cost);
    create(v,u,0,-cost);
}
void SPFA()
{
    int u;
    for (int i = 0; i < V; ++i)
        dis[i] = inf;
    memset(vst,0,sizeof(vst));
    queue<int> q;
    q.push(source);
    vst[source] = 1;
    dis[source] = 0;
    while(!q.empty())
    {
        int v = q.front();
        q.pop();
        for (Edge *i = adj[v]; i != NULL; i = i->next)
        {
            if (!i->flow)
                continue;
            u = i->v;
            if (i->cost + dis[v] < dis[u])
            {
                dis[u] = i->cost + dis[v];
                pree[u] = i;
                pre[u] = v;
                if (!vst[u])
                {
                    q.push(u);
                    vst[u] = true;
                }
            }
        }
        vst[v] = false;
    }
}
void init()
{
    memset(adj, 0, sizeof (adj));
    pp = pool;
}
int Mincost_Maxflow()
{
    int flow = 0, cost = 0;
    while (true)
    {
        SPFA();
        if (dis[sink] == inf)
            break;
        int minn = inf;
        for (int i = sink; i != source; i = pre[i])
            minn = min(minn, pree[i]->flow);
        flow += minn;
        for (int i = sink; i != source; i = pre[i])
        {
            pree[i]->flow -= minn;
            pool[(pree[i] - pool)^0x1].flow += minn;
            cost += minn * pree[i]->cost;
        }
    }
    return cost;
}
int main()
{
    int N,p,m,f,n,s;
    while(scanf("%d %d %d %d %d %d",&N,&p,&m,&f,&n,&s) == 6)
    {
        init();
        source = 0;
        sink = 2*N + 1;
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&day[i]);
            addedge(source,2*i-1,day[i],0);
            addedge(source,2*i,inf,p);
            addedge(2*i,sink,day[i],0);
            if(i + 1 <= N)
                addedge(2*i - 1,2*(i+1) - 1,inf,0);
            if(i + m <=N)
                addedge(2*i - 1,2*(i + m),inf,f);
            if(i + n <=N)
                addedge(2*i - 1,2*(i + n),inf,s);
        }
        int ff = Mincost_Maxflow();
        printf("%d\n",ff);
    }
    return 0;
}

抱歉!评论已关闭.