2017年12月9日提高组 矩阵变换
Description
给定一个 m*n 的矩阵,每个格子里面有一颗不同颜色的宝石。再给出一些关键点,并定义两个矩阵类似为:每种颜色的宝石到各个关键点的距离和原矩阵都相同。
问有多少个矩阵和给定的矩阵类似。当然,自己和自己是类似的。
距离定义为 max{|x1-x2|,|y1-y2|}
Input
m n 1<=m,n<=200
Key_Num 关键点的数目 0<=Key_Num<=50
接下来 Key_Num 行,每行一个二元对(i,j)表示矩阵中第 i 行第 j 列的位置是关键点。
Output
一个整数。答案对 1000000009 取余后的结果。
Sample Input
1 6
1
1 3
Sample Output
4
分析:暴力判断把与各个关键点距离一样的放在同一集合,然后所有集合全排列的积即为答案。
代码
#include <cstdio>
#define N 500
#define mo 1000000009
#define ll long long
using namespace std;
ll jc[N*N],f[N*N],ans;
int a[N][N],b[N][N][55],c[N*N],x[N],y[N],n,m,q;
bool fl;
int max(int i,int j)
{
return i>j?i:j;
}
int fabs(int i)
{
return i>0?i:-i;
}
int find(int xx)
{
if (f[xx]==xx) return xx;
return f[xx]=find(f[xx]);
}
int main()
{
// freopen("transform.in","r",stdin);
// freopen("transform.out","w",stdout);
scanf("%d%d",&n,&m);
scanf("%d",&q);
for (int i=1;i<=n*m;i++)
f[i]=i;
jc[0]=1;
for (int i=1;i<=n*m;i++)
jc[i]=jc[i-1]*i%mo;
for (int i=1;i<=q;i++)
scanf("%d%d",&x[i],&y[i]);
int k=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
a[i][j]=++k;
for (int l=1;l<=q;l++)
b[i][j][l]=max(fabs(i-x[l]),fabs(j-y[l]));
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
if (x[1]-b[i][j][1]>0)
for (int k=y[1]-b[i][j][1];k<=y[1]+b[i][j][1];k++)
if (k>0&&k<=m)
{
fl=false;
for (int l=1;l<=q;l++)
if (b[i][j][l]!=b[x[1]-b[i][j][1]][k][l])
{
fl=true;
break;
}
if (!fl) f[find(a[i][j])]=find(a[x[1]-b[i][j][1]][k]);
}
if (x[1]+b[i][j][1]<=n)
for (int k=y[1]-b[i][j][1];k<=y[1]+b[i][j][1];k++)
if (k>0&&k<=m)
{
fl=false;
for (int l=1;l<=q;l++)
if (b[i][j][l]!=b[x[1]+b[i][j][1]][k][l])
{
fl=true;
break;
}
if (!fl) f[find(a[i][j])]=find(a[x[1]+b[i][j][1]][k]);
}
if (y[1]-b[i][j][1]>0)
for (int k=x[1]-b[i][j][1];k<=x[1]+b[i][j][1];k++)
if (k>0&&k<=n)
{
fl=false;
for (int l=1;l<=q;l++)
if (b[i][j][l]!=b[k][y[1]-b[i][j][1]][l])
{
fl=true;
break;
}
if (!fl) f[find(a[i][j])]=find(a[k][y[1]-b[i][j][1]]);
}
if (y[1]+b[i][j][1]<=m)
for (int k=x[1]-b[i][j][1];k<=x[1]+b[i][j][1];k++)
if (k>0&&k<=n)
{
fl=false;
for (int l=1;l<=q;l++)
if (b[i][j][l]!=b[k][y[1]+b[i][j][1]][l])
{
fl=true;
break;
}
if (!fl) f[find(a[i][j])]=find(a[k][y[1]+b[i][j][1]]);
}
}
for (int i=1;i<=n*m;i++)
c[f[i]]++;
ans=1;
for (int i=1;i<=n*m;i++)
ans=ans*jc[c[i]]%mo;
printf("%lld",ans);
fclose(stdin);
fclose(stdout);
return 0;
}