https://vijos.org/p/1406
两个相邻点相同则权值为0,否则权值为1.
不相邻点权值设为正无穷
然后在上面和下面加上一排数,上面的是起点,下面的是终点
最后Floyd,输出任意一个在起点和终点的距离(G[起点][终点])即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define ms(i,j) memset(i, j, sizeof(i));
#define pa2(a,r,c) for (int j=1;j<=c;j++) printf("%d ", j);putchar('\n');for (int i=1;i<=r;i++) {for (int j=1;j<=c;j++) if (a[i][j]>4000000) printf("x "); else printf("%d ", a[i][j]); putchar('\n');}
using namespace std;
int n,m;
int map[25][25];
int G[2500][2500];
int cnt = 0;
void f(int i, int j, int c)
{
if (j-1>0&&map[i][j-1]==map[i][j])
G[c][c-1]=0;
else if (j-1>0&&map[i][j-1]!=map[i][j])
G[c][c-1]=1;
if (j+1<=m&&map[i][j+1]==map[i][j])
G[c][c+1]=0;
else if (j+1<=m&&map[i][j+1]!=map[i][j])
G[c][c+1]=1;
if (i-1>0&&c-m>0&&map[i-1][j]==map[i][j])
G[c][c-m]=0;
else if (i-1>0&&c-m>0&&map[i-1][j]!=map[i][j])
G[c][c-m]=1;
if (i+1<=n&&map[i+1][j]==map[i][j])
G[c][c+m]=0;
else if (i+1<=n&&map[i+1][j]!=map[i][j])
G[c][c+m]=1;
}
int main ()
{
ms(G,27);
scanf("%d%d%*c", &n,&m);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
map[i][j] = getchar();
}
getchar();
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
f(i,j, ++cnt);
}
}
for (int i=cnt+1;i<=cnt+m;i++)
{
G[i-m][i]=G[i][i-m]=0;
if(i-1>cnt) G[i-1][i]=G[i][i-1]=0;
}
cnt += m;
for (int i=cnt+1;i<=cnt+m;i++)
{
G[i-cnt][i]=G[i][i-cnt]=0;
if(i-1>cnt) G[i-1][i]=G[i][i-1]=0;
}
cnt += m;
for (int k=1;k<=cnt;k++)
for (int i=1;i<=cnt;i++)
for (int j=1;j<=cnt;j++)
if (k!=i&&k!=j&&i!=j)
{
G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
}
printf("%d\n", G[cnt][cnt-m-1]+1);
return 0;
}