题意 是 给一个 n*n 的图 图中的数字代表颜色 上下左右相同颜色可以组成一个块 问 一种颜色的块 和两种颜色的块的个数的最大值
这道题 只求 一种颜色 的 块 可以直接深搜
求两种颜色的块 就需要 想一蛤 , 当然我们可以枚举每两种颜色然后进行深搜,但是复杂度会很高 , 题目还限制了颜色的数的范围是 10 的六次方, 好像可以搞一搞 可以开两个 1e6 的循环 ??? 这时候需要 剪枝 一蛤 ,会发现有很多两种颜色的情况 是不需要跑深搜的 如果 cnt i + cnt j <= ans (当前的ans) 的话我们可以直接退出循环 (不是continue !!!),然后 这个 剪枝很优秀,我们还可以对 每种颜色的cnt进行从大到小, 所有后面小的基本不可能会跑第二个循环 所以 就可以很快的求出来
代码 (不要看代码长, 其实 非常非常简单。。。)
#include<bits/stdc++.h>
using namespace std;
const int N = 255;
const int M = 1e6;
int a[N][N],vis[N][N];
int n;
struct node
{
int cnt,id;
}p[ M + 10 ];
int c[4][2] = {0,1,0,-1,1,0,-1,0};
void dfs1(int x, int y, int cl ,int &tot)
{
vis[x][y] = 1;
tot++;
for(int i=0;i<4;i++) {
int xx = x + c[i][0];
int yy = y + c[i][1];
if(xx < 1 || xx > n || yy < 1 || yy > n) continue;
if(vis[xx][yy] || a[xx][yy] != cl) continue;
dfs1(xx,yy,cl,tot);
}
}
void dfs2(int x,int y,int c1,int c2,int &tot)
{
vis[x][y] = 1;
tot++;
for(int i=0;i<4;i++) {
int xx = x + c[i][0];
int yy = y + c[i][1];
if(xx < 1 || xx > n || yy < 1 || yy > n) continue;
if(vis[xx][yy] || (a[xx][yy] != c1 && a[xx][yy] != c2)) continue;
dfs2(xx,yy,c1,c2,tot);
}
}
bool cmp(node a, node b)
{
return a.cnt > b.cnt;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
scanf("%d", &a[i][j]);
for(int i=0;i<=M;i++){
p[i].id = i;
p[i].cnt = 0;
}
int ans1 = 0, ans2 = 0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(!vis[i][j]) {
int tot = 0;
dfs1(i,j,a[i][j],tot);
ans1 = max(ans1 , tot);
p[a[i][j]].cnt += tot;
}
}
}
sort(p,p+M,cmp);
ans2 = ans1;
printf("%d\n",ans1);
//cout<<ans1<<endl;
for(int i=0;i<=M;i++) {
for(int j=i+1;j<=M;++j) {
if(p[i].cnt + p[j].cnt <= ans2) break;
//cout<<"sddddd"<<endl;
memset(vis,0,sizeof(vis));
for(int rr=1;rr<=n;rr++) {
for(int cc=1;cc<=n;cc++) {
if(!vis[rr][cc]) {
if(a[rr][cc] == p[i].id || a[rr][cc] == p[j].id) {
int tot = 0;
dfs2(rr,cc,p[i].id,p[j].id,tot);
ans2 = max(ans2,tot);
//cout<<ans2<<endl;
}
}
}
}
}
}
printf("%d\n", ans2);
return 0;
}