NOIP模拟 放盒子【费用流】
2017-10-19 20:57
405 查看
题目大意:
给出n个盒子的长和宽,每个盒子都不能旋转且只能装一个长和宽都不大于它的盒子(但能不断嵌套),问最后占地面积最小是多少。(n≤200)解题思路:
即是求被嵌套的盒子面积的最大值。可以用最大费用流来做。
由于套与被套的盒子是一一对应的,不妨把每个盒子拆成两个点i与i’,表示该盒子套与被套,从源点向i连流量为1,费用为0的边;从i’向汇点连流量为1,费用为0的边;若盒子i能套盒子j,则从i向j’连一条费用为area[j]的边;
记得要去重,因为它们会互相连边,就矛盾了。
答案即为去重后初始面积和减去最大费用。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<vector> #include<queue> #define ll long long using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int N=405,INF=0x3f3f3f3f; const int M=N*N*2; struct node { int x,y; friend inline bool operator == (const node &a,const node &b) {return a.x==b.x&&a.y==b.y;} friend inline bool operator < (const node &a,const node &b) { if(a.x==b.x)return a.y<b.y; return a.x<b.x; } }a ; int n,S,T,sum,ans; int tot=1,first ,next[M],to[M],cap[M],cost[M]; int dis ; bool exist ,visit ; queue<int>q; void add(int x,int y,int f,int c) { next[++tot]=first[x],first[x]=tot,to[tot]=y,cap[tot]=f,cost[tot]=c; next[++tot]=first[y],first[y]=tot,to[tot]=x,cap[tot]=0,cost[tot]=-c; } bool SPFA() { for(int i=S;i<=T;i++)visit[i]=false,dis[i]=-INF; dis[S]=0,exist[S]=true; q.push(S); while(!q.empty()) { int u=q.front(); q.pop();exist[u]=false; for(int e=first[u];e;e=next[e]) { int v=to[e]; if(dis[v]<dis[u]+cost[e]&&cap[e]) { dis[v]=dis[u]+cost[e]; if(!exist[v])q.push(v),exist[v]=true; } } } return dis[T]!=-INF; } int dinic(int u,int flow) { if(u==T) { ans+=dis[T]*flow; return flow; } int res=0; visit[u]=1; for(int e=first[u];e;e=next[e]) { int v=to[e]; if(dis[v]==dis[u]+cost[e]&&cap[e]&&!visit[v]) { int delta=dinic(v,min(flow-res,cap[e])); if(delta) { cap[e]-=delta,cap[e^1]+=delta; res+=delta;if(res==flow)break; } } } return res; } void maxflow() { while(SPFA())dinic(S,INF); } int main() { //freopen("lx.in","r",stdin); n=getint(); for(int i=1;i<=n;i++) a[i].x=getint(),a[i].y=getint(); sort(a+1,a+n+1); n=unique(a+1,a+n+1)-a-1; S=0,T=2*n+1; for(int i=1;i<=n;i++) sum+=a[i].x*a[i].y,add(S,i,1,0),add(i+n,T,1,0); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&a[i].x>=a[j].x&&a[i].y>=a[j].y) add(i,j+n,1,a[j].x*a[j].y); maxflow(); cout<<sum-ans; return 0; }
相关文章推荐
- [NOIP模拟][匈牙利算法][费用流]放盒子
- [NOIP2017模拟]造盒子
- [NOIP2017模拟]放盒子
- [NOIP模拟] 方盒子 费用流
- NOIP模拟(10.19)T3 放盒子
- 【2014.8.17NOIP普及组模拟】愤怒的牛
- [NOIP模拟2015.10.06]C
- 紫书章六例题五 移动盒子 UVA 12657 (数组模拟双向链表)
- [JZSC2017] 【NOIP2017提高组模拟6.28】总结
- 【NOIP模拟】计数
- NOIP模拟17.9.22
- 【模拟】[NOIP2011提高组]铺地毯
- JZOJ 5185. 【NOIP2017提高组模拟6.30】tty's sequence
- [NOIP模拟] 证明 proof - 最短路
- NOIP模拟考试
- JZOJ 5386. 【NOIP2017提高A组模拟9.23】碎
- [JZOJ5390]【NOIP2017提高A组模拟9.26】逗气
- [NOIP模拟2015.10.24]tty的求助III
- jzoj. 3452. 【NOIP2013中秋节模拟】长方形(rectangle)
- JZOJ__Day 3:【NOIP普及模拟】排序(sort)