[NOIP模拟][匈牙利算法][费用流]放盒子
2017-10-19 20:46
239 查看
题目描述:
题目大意:给出n(≤200)个盒子,第i个盒子长xi,宽yi,一个盒子可以放入长宽都大于等于它的盒子里,并且每个盒子里只能放入一个盒子(可以嵌套),嵌套的盒子的占地面积等于最外层的盒子的占地面积,求最小的占地面积之和。
样例输入:
3
1 1
1 2
2 1
样例输出:
4
题目分析:
这道题即可以用二分图最大匹配做,也可以用费用流做。
二分图匹配:我们可以把所有盒子以面积大小排序,最大的排前面,建图,两边都是一样的,即排序后的所有盒子。如果左边一个盒子能被放进右边另一个盒子,就连一条边,匹配过程,就是盒子被放入另一个盒子的过程,因为是以面积降序排序,也就是说,我们做得的最大匹配就是能够被放的盒子的最大面积和,即最大节约面积,于是用总面积减去节约的面积就是答案。正确性:一个盒子被放入另一个盒子后是不影响它自己接受其它盒子的,那么我们就尽量先让那些大盒子被放。
二分图最大匹配当然是用匈牙利做啦,如果不会,可以看一下这个人的讲解,个人认为讲解得十分通俗易懂,请戳: 趣写算法系列之–匈牙利算法
费用流:与上面类似,对上面左右两边的点建一个超级源点和超级汇点,源点和汇点连向那些盒子的代价为0,而盒子之间连边代价就是被放的那个盒子的面积,每条边的流量为1,因为盒子只能嵌套一次。然后做一遍最大费用流,得到的就是最大节约面积。
附代码:
二分图匹配:
题目大意:给出n(≤200)个盒子,第i个盒子长xi,宽yi,一个盒子可以放入长宽都大于等于它的盒子里,并且每个盒子里只能放入一个盒子(可以嵌套),嵌套的盒子的占地面积等于最外层的盒子的占地面积,求最小的占地面积之和。
样例输入:
3
1 1
1 2
2 1
样例输出:
4
题目分析:
这道题即可以用二分图最大匹配做,也可以用费用流做。
二分图匹配:我们可以把所有盒子以面积大小排序,最大的排前面,建图,两边都是一样的,即排序后的所有盒子。如果左边一个盒子能被放进右边另一个盒子,就连一条边,匹配过程,就是盒子被放入另一个盒子的过程,因为是以面积降序排序,也就是说,我们做得的最大匹配就是能够被放的盒子的最大面积和,即最大节约面积,于是用总面积减去节约的面积就是答案。正确性:一个盒子被放入另一个盒子后是不影响它自己接受其它盒子的,那么我们就尽量先让那些大盒子被放。
二分图最大匹配当然是用匈牙利做啦,如果不会,可以看一下这个人的讲解,个人认为讲解得十分通俗易懂,请戳: 趣写算法系列之–匈牙利算法
费用流:与上面类似,对上面左右两边的点建一个超级源点和超级汇点,源点和汇点连向那些盒子的代价为0,而盒子之间连边代价就是被放的那个盒子的面积,每条边的流量为1,因为盒子只能嵌套一次。然后做一遍最大费用流,得到的就是最大节约面积。
附代码:
二分图匹配:
#include<iostream> #include<cstring> #include<string> #include<cstdlib> #include<cstdio> #include<ctime> #include<cmath> #include<cctype> #include<iomanip> #include<algorithm> using namespace std; int n,ans,belong[205]; bool line[205][205],vis[205]; struct node{ int x,y,w; }box[205]; int readint() { char ch;int i=0,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') {ch=getchar();f=-1;} for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0'; return i*f; } bool comp(const node &a,const node &b) { return a.w>b.w; } bool find(int x) { for(int i=1;i<x;i++) { if(line[x][i]==true&&vis[i]==false) { vis[i]=true; if(belong[i]==0||find(belong[i])) { belong[i]=x; return true; } } } return false; } int main() { n=readint(); for(int i=1;i<=n;i++) { box[i].x=readint(); box[i].y=readint(); box[i].w=box[i].x*box[i].y; } sort(box+1,box+1+n,comp); for(int i=1;i<=n;i++) { ans+=box[i].w; for(int j=i+1;j<=n;j++) { if(box[i].x>=box[j].x&&box[i].y>=box[j].y) line[j][i]=true; } } for(int i=2;i<=n;i++) { memset(vis,false,sizeof(vis)); if(find(i)==true) ans-=box[i].w; } printf("%d",ans); return 0; }
相关文章推荐
- NOIP模拟 放盒子【费用流】
- HDU 1528 Card Game Cheater(二分图匹配+匈牙利算法+模拟)
- NOIP模拟(10.19)T3 放盒子
- [NOIP2017模拟]放盒子
- NOIP模拟 NYG的背包 [高山算法]
- HDU 1281 棋盘游戏(二分图匹配+匈牙利算法+模拟)
- [NOIP模拟] 方盒子 费用流
- [jzoj]3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll)(匈牙利-二分图最大匹配)
- JZOJ4744. 【NOIP2016提高A组模拟9.2】同余 一类比较好的分类思想+根号算法
- 小白算法练习 hdu courses 1083 匈牙利算法 dfs 邻接矩阵 vector模拟邻接表
- [NOIP2017模拟]造盒子
- JAVA实现简单抢红包算法(模拟真实抢红包)
- JZOJ 3506. 【NOIP2013模拟11.4A组】善良的精灵
- NOIP模拟 赌博游戏【概率dp】
- 高中OJ3514. 【NOIP2013模拟11.6B组】最小比例
- Pku acm 1469 COURSES 数据结构题目解题报告(十一)---- 匈牙利算法求二分图的最大匹配
- 【2016.10.5NOIP普及模拟】zy的秘密
- 【NOIP2016提高A组模拟9.9】运输妹子
- [NOIP2017模拟]疯狂的01串
- NOIP基础算法与经典问题01 一维前缀和