【HNOI2014】画框
题面
题解
这又是一种套路啊233
将\(\sum a_i\)和\(\sum b_i\)分别看做\(x\)和\(y\),投射到平面直角坐标系中,于是就是找\(xy\)最小的点
于是可以先找出\(x\)最小的点\(\mathrm{A}\)和\(y\)最小的点\(\mathrm{B}\),然后找到在\(\mathrm{AB}\)下方的最远的点\(\mathrm{C}\)
即\(\overrightarrow{\mathrm{AB}} \times \overrightarrow{\mathrm{AC}}\)最小
\because \overrightarrow{\mathrm{AB}} \times \overrightarrow{\mathrm{AC}} &= (x_{\mathrm{B}} - x_{\mathrm{A}})(y_{\mathrm{C}} - y_{\mathrm{A}}) - (y_{\mathrm{B}} - y_{\mathrm{A}})(x_\mathrm{C} - x_\mathrm{A}) \\
&= (x_\mathrm B - x_\mathrm A) \times y_\mathrm C + (y_\mathrm A - y_\mathrm B) \times x_\mathrm C + y_\mathrm B x_\mathrm A - x_\mathrm B y_\mathrm A
\end{aligned}
\]
于是将权值改成\(\mathrm{g}[i][j] = (y_\mathrm A - y_\mathrm B) \times a[i][j] + (x_\mathrm B - x_\mathrm A)\times b[i][j]\),然后用\(\mathrm{KM}\)找出\(\mathrm C\)。
找到\(\mathrm C\)之后用叉积判断一下\(\mathrm C\)是不是在\(\mathrm{AB}\)的下方,如果是的话,就递归处理\(\mathrm{AC, CB}\)
复杂度\(\mathrm{O}(\)能过\()\)
代码
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<climits>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))
inline int read()
{
int data = 0, w = 1; char ch = getchar();
while(ch != '-' && (!isdigit(ch))) ch = getchar();
if(ch == '-') w = -1, ch = getchar();
while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
return data * w;
}
const int N(75);
int T, n, a[N][N], b[N][N], ans;
struct vector { int x, y; };
inline vector operator - (const vector &lhs, const vector &rhs)
{ return (vector) {lhs.x - rhs.x, lhs.y - rhs.y}; }
inline int operator * (const vector &lhs, const vector &rhs)
{ return lhs.x * rhs.y - lhs.y * rhs.x; }
int g[N][N], lx[N], ly[N], visx[N], visy[N], match[N];
bool hungary(int x)
{
visx[x] = 1;
for(RG int to = 1; to <= n; to++)
if(!visy[to] && lx[x] + ly[to] == g[x][to])
{
visy[to] = true;
if(!match[to] || hungary(match[to])) return (match[to] = x, true);
}
return false;
}
void build(int valx, int valy)
{
for(RG int i = 1; i <= n; i++) for(RG int j = 1; j <= n; j++)
g[i][j] = -(valx * a[i][j] + valy * b[i][j]);
}
vector KM()
{
for(RG int i = 1; i <= n; i++)
ly[i] = 0, lx[i] = *std::max_element(g[i] + 1, g[i] + n + 1);
memset(match, 0, sizeof match);
for(RG int x = 1; x <= n; x++)
while(1)
{
clear(visx, 0), clear(visy, 0);
if(hungary(x)) break;
int inc = INT_MAX;
for(RG int i = 1; i <= n; i++) if(visx[i])
for(RG int j = 1; j <= n; j++) if(!visy[j])
inc = std::min(inc, lx[i] + ly[j] - g[i][j]);
for(RG int i = 1; i <= n; i++) if(visx[i]) lx[i] -= inc;
for(RG int i = 1; i <= n; i++) if(visy[i]) ly[i] += inc;
}
vector ans = (vector) {0, 0};
for(RG int i = 1; i <= n; i++)
ans.x += a[match[i]][i], ans.y += b[match[i]][i];
return ans;
}
void solve(const vector &A, const vector &B)
{
build(A.y - B.y, B.x - A.x);
vector C = KM(); ans = std::min(ans, C.x * C.y);
if((B - A) * (C - A) >= 0) return;
solve(A, C), solve(C, B);
}
int main()
{
T = read();
while(T--)
{
n = read();
for(RG int i = 1; i <= n; i++)
for(RG int j = 1; j <= n; j++)
a[i][j] = read();
for(RG int i = 1; i <= n; i++)
for(RG int j = 1; j <= n; j++)
b[i][j] = read();
build(1, 0); vector A = KM();
build(0, 1); vector B = KM();
ans = std::min(A.x * A.y, B.x * B.y);
solve(A, B); printf("%d\n", ans);
}
return 0;
}
【HNOI2014】画框的更多相关文章
- 【LG3236】[HNOI2014]画框
[LG3236][HNOI2014]画框 题面 洛谷 题解 和这题一模一样. 将最小生成树换成\(KM\)即可. 关于复杂度,因为决策点肯定在凸包上,且\(n\)凸包的期望点数为\(\sqrt {\l ...
- bzoj 3571: [Hnoi2014]画框
Description 小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框.为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和.对于第 幅画与第 个画框的配对,小T都 ...
- [HNOI2014]画框
题目描述 小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框.为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和. 对于第 幅画与第 个画框的配对,小T都给出了这个配 ...
- BZOJ3571 & 洛谷3236:[HNOI2014]画框——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3571 https://www.luogu.org/problemnew/show/P3236 小T ...
- BZOJ3571 : [Hnoi2014]画框
题目是要求最小乘积最小权匹配, 将一种方案看做一个二维点(x,y),x=a值的和,y=b值的和,所有方案中只有在下凸壳上的点才有可能成为最优解 首先要求出两端的方案l,r两个点 l就是a值的和最小的方 ...
- bzoj3571: [Hnoi2014]画框 最小乘积匹配+最小乘积XX总结,
思路大概同bzoj2395(传送门:http://www.cnblogs.com/DUXT/p/5739864.html),还是将每一种匹配方案的Σai看成x,Σbi看成y,然后将每种方案转化为平面上 ...
- luogu P3236 [HNOI2014]画框
传送门 我们把一种方案的\(\sum a_{i,j}\)和\(\sum b_{i,j}\)看成点\((\sum a_{i,j},\sum b_{i,j})\),那么就只要求横纵坐标之积最小的点,类似于 ...
- 【bzoj3751】 Hnoi2014—画框
http://www.lydsy.com/JudgeOnline/problem.php?id=3571 (题目链接) 题意 给出一个$2*N$个点的二分图,$N*N$条边,连接$i$和$j$的边有两 ...
- BZOJ 3571 [Hnoi2014]画框(最小乘积完美匹配)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3571 [题目大意] 给出一张二分图,每条边上有a,b两个值,求完美匹配, 使得suma ...
- 洛谷P3236 [HNOI2014]画框(最小乘积KM)
题面 传送门 题解 我似乎连\(KM\)都不会打啊→_→ 和bzoj2395是一样的,只不过把最小生成树换成\(KM\)了.因为\(KM\)跑的是最大权值所以取个反就行了 //minamoto #in ...
随机推荐
- 将CAGradientLayer用作maskView的遮罩图层
将CAGradientLayer用作maskView的遮罩图层 说明 CAGradientLayer可以用作alpha遮罩,供maskView使用,这两种东西都是非常偏门的东西,但是,偏门不代表功能不 ...
- [翻译] BTSimpleRippleButton
BTSimpleRippleButton https://github.com/balram3429/btSimpleRippleButton This is a custom button for ...
- 辉光UIView的category
辉光UIView的category 本人视频教程系类 iOS中CALayer的使用 效果如下: 源码: UIView+GlowView.h 与 UIView+GlowView.m // // UI ...
- Linux less/more命令详解
less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻, 只能往后面看,但若使用了 less 时,就可以使用 [pageup] [pagedown] 等按键的功能来 ...
- 铁乐学python_day01-作业
第一题:使用while循环输入 1 2 3 4 5 6 8 9 10 # 使用while循环输入 1 2 3 4 5 6 8 9 10 count = 0 while (True) : count = ...
- November 7th 2016 Week 46th Monday
A friend is one who knows you and loves you just the same. 朋友是懂你并爱你的人. Friendship means inclusion, l ...
- c++中堆、栈内存分配
转自:https://blog.csdn.net/qingtingchen1987/article/details/7698415 一个由C/C++编译程序占用内存分为以下几个部分1.栈区(stack ...
- 【转载】QPS,用户平均等待时间,服务器平均请求处理时间
转自:http://www.cnblogs.com/coldplayerest/archive/2012/06/28/2567656.html 1. 计算网络的QPS时,必须要指定并发度,否则没有意义 ...
- BZOJ1135:[POI2009]Lyz(线段树,Hall定理)
Description 初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人.xi为负,则代表走了这么多人 ...
- 2938: [Poi2000]病毒
Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码 ...