最小内积 北航第十二届程序设计竞赛网络预赛
2016-12-12 22:01
232 查看
题目描述 ( 题目链接
BUAA 609 )
给定两个n维向量
A⃗ =(x1,x2,⋯,xn)
和
B⃗ =(y1,y2,⋯,yn)
,定义它们的点积为
A⃗ ⋅B⃗ =∑1≤i≤nxi⋅yi
对于每个向量,它的每个分量互不相同,而且任意两个分量均可交换位置。
求一种交换策略使得
A⃗ 与
B⃗ 的内积最小,如果有多种满足条件的交换策略,那么还要使得交换总次数最少。
请你给出最少的交换次数及交换后
A⃗ ⋅B⃗ 的值。
输入
第一行包含一个正整数T,表示有
T组测试数据。
接下来依次给出每组测试数据。对于每组测试数据:
第一行包含一个正整数
n,表示向量维数。
第二行包含
n个整数,第
i
个整数表示
xi。
第三行包含
n个整数,第
i
个整数表示
yi。
保证在一行中的每个整数互不相等,而且每个整数之间有恰好一个空格,没有其他额外的空格。
1≤T≤100,1≤n≤105,0≤|xi|,|yi|≤106
输出
对于每组数据输出一行,包含两个整数,表示A⃗ 和
B⃗ 的内积和最少的交换次数。
对于本题,输出中在一行的每个整数之间用恰好一个空格隔开,不能有其他额外空格。
输入样例
1 2 1 2 2 1[/code]
输出样例
4 0[/code]
出题人是
yic 。
首先考虑问题的第一部分:如何使内积最小?以二维向量为例, (x1,x2)⋅(y1,y2)=x1y1+x2y2
。由于各分量互不相同,不妨设x1<x2,则
(x1,x2)⋅(y1,y2)−(x1,x2)⋅(y2,y1)=x1(y1−y2)+x2(y2−y1)=(x1−x2)(y1−y2)
因此 (x1,x2)⋅(y1,y2)<(x1,x2)⋅(y2,y1)
当且仅当 y1>y2
。
推广到多维的情况,若存在 i,j(i≠j)
使 xi<xj
且 yi>yj
,则我们可以交换 yi
和 yj
以获得更优的结果,因此最终结果一定有 ∀i≠j∈[1,n](xi−xj)(yi−yj)<0
,即 A⃗
的最小分量对应 B⃗
的最大分量, A⃗
的次小分量对应 B⃗
的次大分量,……,以此类推。
知道了最终的对应关系后我们来考虑如何交换,稍加思考可知,对于一对位置 (i,j)
,交换 A⃗
与交换 B⃗
的结果是一样的,因此可以只交换 A⃗
的分量,问题转换为给一个数列,要排列成指定顺序的最少交换次数。
我们从任意一个数出发,找到它的目标位置及这个位置上的数字,再找到新数的目标位置,这样不停找下去,由于不可能有两个不同的数对应同一个位置,因此最终必然形成一个长度为L
的环,不同的环之间没有必要进行交换操作,在同一个环内每把一个数移动到目标位置都会使环的长度减一,总共需要交换
L−1
次。因此最终答案就是 n
减去环的个数。
注意本题没有要求只能对两相邻分量进行交换,因此不用计算逆序对数,另外内积会超过
int范围,需用
long long型数据。
附上AC代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int ma=100005; int n; struct node { int data; int xi,yi; } nodea[ma],nodeb[ma]; bool vis[ma]; int cmp(node a,node b) { return a.data<b.data; } bool dmp(node a,node b) { return a.data>b.data; } bool cmp2(node a,node b) { return a.xi<b.xi; } int countnum(node nodeaa[]) { int ans=0; memset(vis,0,sizeof(vis)); for(int i=0; i<n; ++i) ///找环 { if(vis[i]) continue; vis[i]=1; int ne=i; ++ans; while(nodeaa[ne].yi!=i) { ne=nodeaa[ne].yi; vis[ne]=1; } } return n-ans; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0; i<n; ++i) { scanf("%d",&nodea[i].data); nodea[i].xi=i; ///排序前的下标 } sort(nodea,nodea+n,cmp); ///升序 for(int i=0; i<n; ++i) { scanf("%d",&nodeb[i].data); nodeb[i].xi=i; } sort(nodeb,nodeb+n,dmp); long long ans=0; ///求最小内积 for(int i=0; i<n; ++i) ans+=(long long)nodea[i].data*nodeb[i].data; for(int i=0; i<n; ++i) ///求最小交换次数 nodea[i].yi=nodeb[i].xi; sort(nodea,nodea+n,cmp2); long long num=countnum(nodea); printf("%lld %d\n",ans,num); } return 0; } /** 10 5 1 2 5 8 0 3 5 9 8 7 71 3 */
这道题真的是坑死人不偿命,被卡了两天才A出来。
相关文章推荐
- 北航第十二届程序设计竞赛网络预赛__M最小内积
- 北航第十二届程序设计竞赛网络预赛题解
- # NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(落后的小岛-最小生成树-并查集迭代路径优化与不优化对比)[Hobo]
- 第十二届北京师范大学程序设计竞赛网络预赛 2014-04-19
- 第十二届北航程序设计竞赛预赛
- 第十二届北航程序设计竞赛决赛网络同步赛: 浪哥的烦恼
- 北航第十一届程序设计竞赛网络预赛题解
- 北航第十二届程序设计竞赛:G 火柴棍摆数字
- “亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (K L题解) CSS出题
- ACM学习历程—NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)A题 小女警的异世界之战(dfs && 分治)
- 『NYIST』第九届河南省ACM竞赛队伍选拔赛[正式赛二]-最小内积(第八届北京师范大学程序设计竞赛决赛)
- ACM学习历程—NPU1086 随机数 2015年陕西省程序设计竞赛网络预赛(正式赛)C题 (计数排序 || set容器)
- 第八届北航程序设计大赛网络预赛解题报告
- 第八届北航程序设计大赛网络预赛 解题目报告
- ACM学习历程—NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)F题 和谐的比赛(递推)
- “Wishare杯”南邮第八届大学生程序设计竞赛之网络预赛 题解报告
- NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(小女警的异世界之战-前序中序求后序)
- “亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (K L题解)
- “亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 A noj 2073 FFF [ 二分图最大权匹配 || 最大费用最大流 ]
- NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(约翰·亨利-dp)