Codeforces1146G. Zoning Restrictions

Description

You are planning to build housing on a street. There are n spots available on the street on which you can build a house. The spots are labeled from 1 to n from left to right. In each spot, you can build a house with an integer height between 0 and h.ui

In each spot, if a house has height a, you can gain a2 dollars from it.spa

The city has m zoning restrictions though. The i-th restriction says that if the tallest house from spots li to ri is strictly more than xi, you must pay a fine of ci.rest

You would like to build houses to maximize your profit (sum of dollars gained minus fines). Determine the maximum profit possible.code

Input

The first line contains three integers n,h,m (1≤n,h,m≤50) — the number of spots, the maximum height, and the number of restrictions, respectively.three

Each of the next m lines contains four integers li,ri,xi,ci (1≤li≤ri≤n, 0≤xi≤h, 1≤ci≤5000).ip

Output

Print a single integer denoting the maximum profit you can make.ci

Solution

大意就是建房子,房子最大高度爲h,對於高度爲i的建築,收益爲i*i。如今有m個限制,對於第i個限制,在li~ri這段區間內,高度若是有超過xi的須要罰款ci元。問最大收益
初始不計限制的時候最大的貢獻天然是\(n\times h\times h\)
但還要考慮損失
考慮最小割來求損失
設一個超級源S和超級匯T
將每個點拆成0~h-1即h個點
將0點與S連一條正無窮的邊
隨後對於這h個點:input

  • 第i個點與第i+1個點之間連一條\(h\times h-i\times i\)的邊,表示損失

割掉第i個點與第i+1個點之間的連邊就表明選了第i個點
隨後,對於每一個限制it

  • li~ri區間內的第xi個點與該點連一條正無窮的邊,由於這條邊不可能被割
    該點再與T連一條ci的邊,表示損失

最後輸出便可
(第一次打sap,以前都在打dinic呢)io

#include <cstdio>
#include <algorithm>
#define inf 1000000007
#define S 4000
#define T 4001
#define M 20001
#define N 5001
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
#define id(x,y) (x-1)*(h+1)+y+1
using namespace std;
int len,n,h,m,l,r,x,c,cnt,ans,i,j,go[M],to[M],last[N],w[M],dis[N],gap[N],cur[N];
void make(int x,int y,int z)
{
    go[++len]=y;to[len]=last[x];w[len]=z;last[x]=cur[x]=len;
}
void add(int x,int y,int z)
{
    make(x,y,z);
    make(y,x,0);
}
int sap(int x,int flow)
{
    if (x==T) return flow;
    int tmp,have=flow;
    for (int i=last[x];i;i=to[i])
    {
        last[x]=i;
        if (w[i] && dis[x]==dis[go[i]]+1)
        {
            tmp=sap(go[i],min(have,w[i]));
            w[i]-=tmp;w[i^1]+=tmp;have-=tmp;
            if (!have) return flow;
        }
    }
    last[x]=cur[x];
    if (!--gap[dis[x]]) dis[S]=T;
    ++gap[++dis[x]];
    return flow-have;
}
int main()
{
    open("restrictions");
    scanf("%d%d%d",&n,&h,&m);
    len=1;
    for (i=1;i<=n;i++)
    {
        add(S,id(i,0),inf);
        for (j=0;j<h;j++)
        {
            add(id(i,j),id(i,j+1),h*h-j*j);
        }
    }
    cnt=id(n,h);
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&l,&r,&x,&c);
        if (x==h) continue;
        add(++cnt,T,c);
        for (j=l;j<=r;j++)
            add(id(j,x+1),cnt,inf);
    }
    ans=n*h*h;
    while (dis[S]<T) ans-=sap(S,inf);
    printf("%d",ans);
    return 0;
}
相關文章
相關標籤/搜索