『アルゴリズムコンテスト進級ガイド』七夕まつり
1767 ワード
リンク:http://exam.upc.edu.cn/problem.php?cid=1430&pid=12
件名:
n*m行列におけるT個の点の座標を与え,隣接する座標を移動させることにより,各行(各列)が持つ点数を等しくできるか否かを判断し,最小移動ステップ数を出力する.
第1とnも隣接していると見なす.
考え方:
下のキャンディ転送リンクを参照してください.
関連する問題:キャンディは問題を伝達して、n人の学友
参考:
https://www.cnblogs.com/CtrlCV/p/5626194.html
https://blog.csdn.net/moep0/article/details/52506765
コード:
件名:
n*m行列におけるT個の点の座標を与え,隣接する座標を移動させることにより,各行(各列)が持つ点数を等しくできるか否かを判断し,最小移動ステップ数を出力する.
第1とnも隣接していると見なす.
考え方:
下のキャンディ転送リンクを参照してください.
関連する問題:キャンディは問題を伝達して、n人の学友
参考:
https://www.cnblogs.com/CtrlCV/p/5626194.html
https://blog.csdn.net/moep0/article/details/52506765
コード:
#include
#define LL long long
using namespace std;
const int maxn = 1e5+5;
LL t, n, m, x[maxn], y[maxn], s1[maxn], s2[maxn];
void solve()
{
LL ans = 0, sum = 0;
if(t%n==0){
for(int i=1; i<=n; ++i) sum += x[i];
int average = sum/n;
for(int i=1; i<=n; ++i) x[i] -= average;
for(int i=1; i<=n; ++i) s1[i] = s1[i-1]+x[i];
sort(s1+1, s1+n+1);
average = s1[(n+1)/2];
for(int i=1; i<=n; ++i) ans += abs(average-s1[i]);
}
sum = 0;
if(t%m==0){
for(int i=1; i<=m; ++i) sum += y[i];
int average = sum/m;
for(int i=1; i<=m; ++i) y[i] -= average;
for(int i=1; i<=m; ++i) s2[i] = s2[i-1]+y[i];
sort(s2+1, s2+m+1);
average = s2[(m+1)/2];
for(int i=1; i<=m; ++i) ans += abs(average-s2[i]);
}
printf("%lld
", ans);
}
int main()
{
int a, b;
scanf("%lld%lld%lld", &n, &m, &t);
for(int i=1; i<=t; ++i)
scanf("%d%d", &a, &b), x[a]++, y[b]++;
if(t%n!=0&&t%m!=0){
printf("impossible
");
return 0;
}
if(t%n==0&&t%m==0) printf("both ");
else if(t%n==0) printf("row ");
else if(t%m==0) printf("column ");
solve();
}
/***
2 8 8
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
*/