题意:
给定一个nn的矩阵,一开始上面没有任何颜色(也就是都为0)。之后进行n
n次染色,每次选择一个[1,n
n]的颜色,且每种颜色都只会被选择一次。然后在矩阵上选择任意大小和任意位置的子矩阵进行染色,规定后面的染色会覆盖前面的染色。在给出矩阵最终的染色情况下,问第一次染色选择的颜色种类可能有多少种。
分析:
如果(x,y)处染色的次数大于等于2,那么(x,y)处的颜色肯定不能作为第一次染色选择的颜色。因此我们用一个矩阵S,S[i][j]表示(i,j)处的染色次数,初值均为0。然后对每种颜色记录他的左上角点和右下角点,使得这两点确定的矩阵内所有元素加一,在这里我们可以使用二维差分数组进行优化。之后判断每个位置的S[i][j],若S[i][j]大于等于2,则置(i,j)处的颜色的标记数组为0,表示该种颜色无法用于第一次染色。之后用ans统计一遍标记数组从1~nn中1的个数即可。
写完以上思想的代码快速交了一发,结果过了90%,肯定是还有什么特殊情况没有考虑。我们考虑这种情况:假如给出的矩阵里面只有一种颜色,那么通过以上思想求出的答案是nn,但是答案显然是n
n-1才对。因此我们特判一下这种情况,就能顺利通过此题了。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[1005][1005],S[1005][1005]={0};
int xmi[1000005],xmx[1000005],ymi[1000005],ymx[1000005];
bool V[1000005];
int main()
{
int i,j,n,id,ans=0;
scanf("%d",&n);
for(i=1;i<=n*n;i++)xmi[i]=ymi[i]=1e9,xmx[i]=ymx[i]=0,V[i]=1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&a[i][j]),id=a[i][j];
xmi[id]=min(xmi[id],i);
xmx[id]=max(xmx[id],i);
ymi[id]=min(ymi[id],j);
ymx[id]=max(ymx[id],j);
}
for(i=1;i<=n*n;i++)
{
if(!xmx[i])continue;
ans++;
S[xmi[i]][ymi[i]]++;
S[xmi[i]][ymx[i]+1]--;
S[xmx[i]+1][ymi[i]]--;
S[xmx[i]+1][ymx[i]+1]++;
}
if(ans==1){printf("%d\n",n*n-1);return 0;}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
S[i][j]+=S[i-1][j]+S[i][j-1]-S[i-1][j-1];
if(S[i][j]>=2)V[a[i][j]]=0;
}
for(ans=0,i=1;i<=n*n;i++)ans+=V[i];
printf("%d\n",ans);
return 0;
}
京公网安备 11010502036488号