首先要说的是个数学小知识。
给你两个N维向量(x1,x2,x3,…,xN) 和(y1,y2,y3,…,yN)
你可以任意交换这两个向量中分量的顺序,你要做的事情就是使得这两个向量的内积最小
即 x1 * y1 + x2 * y2 + x3 * y3 + … + xN * yN 最小
解法:将X从小到大排列,再将Y从大到小排列,相乘就是答案。
思路:
当N = 2时,我们来看看
假定此时X已经按照从小到大排序,即x1 < x2;
我们来比较一下此时两种内积的大小,
x1y1 + x2y2 - x1y2 - x2y1 = x1(y1 - y2) + x2(y2 - y1) = (x1 - x2) * (y1 - y2)
可知当y1 > y2,即Y逆序排列时,内积最小。
下面考虑当N > 2的情况
不妨假设最小内积时的Y不是逆序排列,那么一定存在这样的i j使得yi < yj,这样我们由N = 2时的情况可以知道,交换yi和yj后的内积会更小,这显然不是最小内积的Y。这样就证明完成了。
sort(a,a + n);sort(b,b + n);
for(int i = 0;i < n;i++)
ans += a[i] * b[n - i - 1];
再来,给定一个0,1矩阵,只能交换相邻的两行,问最少需要多少次交换才能把矩阵换成下三角矩阵,保证给定的矩阵可以化成下三角矩阵。
对此,我们对于每一行只需要记录最后一个1出现的位置即可,当每一行有多种选择时,选择离它最近的行即可。
#include <bits/stdc++.h>
#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define INF 0x3f3f3f3f
#define eps 1e-5
typedef long long LL;
const double pi = acos(-1.0);
const long long mod = 25 * 1E8;
using namespace std;
int N;
int M[MAXN][MAXN];
int a[MAXN];
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
ios_base::sync_with_stdio(0);cin.tie(0);
int res = 0;
for(int i = 0;i < N;i++)
{
a[i] = -1;
for(int j = 0;j < N;j++)
{
if(M[i][j] == 1)
a[i] = j;
}
}
for(int i = 0;i < N;i++)
{
int pos = -1;
for(int j = i;j < N;j++)
{
if(a[i] <= i)
{
pos = j;
break;
}
}
for(int j = pos;j > i;j--)
{
swap(a[j],a[j - 1]);
res++;
}
}
return 0;
}
PS:最近事情很多 心情很烦 觉得是该开始重新振作起来了 谢谢来自某人的教诲 正如你一如既往的对我那样。