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
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
Print a single integer denoting the maximum profit you can make.ci
大意就是建房子,房子最大高度爲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個點之間的連邊就表明選了第i個點
隨後,對於每一個限制it
最後輸出便可
(第一次打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; }