Description:
在一个N*N的区域玩积木游戏,每个单元格正好跟积木的底面相等,每个单元格里放有若干个积木,Alice想重新摆放积木,使得每个单元格最多只能放一个积木,并且所有积木正好形成一个矩形。
把一个积木从一个位置移到另一个位置称为一次操作。
给出初始状态,编程计算最少需要多少次操作才能达到上述要求。
Input
第一行包含两个整数N和M(1<=N<=100,1<=M<=N^2),表示区域大小以及积木的数量。
接下来M行,每行包含两个整数R和C(1<=R,C<=N),表示每个积木放置的位置。
Output
输出最少操作次数。输入保证有解。
Solution
Fi,j
为点
(i,j)
的被积木所占的个数前缀和。
枚举矩形长
i
,则宽
再枚举矩形右下角,利用前缀和得出需移步数。
Program
C++
#include<iostream>
#include<fstream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int ans,n,m,r,c,f[101][101];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&r,&c);
f[r][c]=1;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
}
int j;
ans=2147483647;
for (int i=1;i<=n;i++)
if ((m/i<=n)&&(m%i==0))
{
j=m/i;
for (int p=i;p<=n;p++)
for (int q=j;q<=n;q++)
ans=min(ans,m-(f[p][q]-f[p-i][q]-f[p][q-j]+f[p-i][q-j]));
}
printf("%d\n",ans);
}
Pascal
uses
math;
var
ans,n,m,r,c,i,j,p,q:longint;
f:array [0..100,0..100] of longint;
begin
readln(n,m);
for i:=1 to m do
begin
readln(r,c);
f[r][c]:=1;
end;
for i:=1 to n do
for j:=1 to n do
f[i][j]:=f[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1];
ans:=maxlongint;
for i:=1 to n do
if (m div i<=n) and (m mod i=0) then
begin
j:=m div i;
for p:=i to n do
for q:=j to n do
ans:=min(ans,m-(f[p][q]-f[p-i][q]-f[p][q-j]+f[p-i][q-j]));
end;
writeln(ans);
end.