B. Morning Jogging
Example
input
2
2 3
2 3 4
1 3 5
3 2
2 3
4 1
3 5
output
2 3 4
5 3 1
2 3
4 1
3 5
题目大意:
一个n行m列的数组,在每一行中任意交换数字,使得最终每一列的最小值之和最小。
思路:
贪心,把全部数升序排序,用前m个数填到每一列的某个数组里,剩下的位置按照数组里有的数字随便填。实现有点麻烦。
代码:
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#define AC 0
#define endl '\n'
#define Please return
#define int long long
using namespace std;
const int N=1e2+7;
int ans[N][N];
int b[10007];
map<int,int>ma[N];
signed main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
int k=0;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
int a;
cin>>a;
b[++k]=a;
ma[i][a]++;
}
}
sort(b+1,b+k+1);
int now=1;
map<int,int>::iterator it;
for(int i=1;i<=m;++i)//b里选前m个
{
for(int j=1;j<=n;++j)//当前列
{
if(ma[j].find(b[i])!=ma[j].end())//有这个元素
{
ans[j][now++]=b[i];
ma[j][b[i]]--;
if(ma[j][b[i]]==0)ma[j].erase(b[i]);
break;
}
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
if(ans[i][j]==0)//这里空着
{
it=ma[i].begin();
ans[i][j]=it->first;
it->second--;
if(it->second==0)ma[i].erase(it);
}
}
}
for(int i=1;i<=n;++i)
{
ma[i].clear();
for(int j=1;j<=m;++j)
{
cout<<ans[i][j]<<' ';
ans[i][j]=0;//顺便初始化
}
cout<<endl;
}
}
Please AC;
}
用几个样例试试就会发现,决定最终和最小的其实只是数组里的几个最小值,所以把它们分别放在每一列里,就可以构造出答案了。