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.

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

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.

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

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.

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

Output

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

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個點:

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

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

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

最後輸出即可
(第一次打sap,之前都在打dinic呢)

#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];
void make(int x,int y,int z)
{
    go[++len]=y;to[len]=last[x];w[len]=z;last[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])
    {
        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;
        }
    }
    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;
}

Tags: