F

来源:互联网 发布:四川广电网络全称 编辑:程序博客网 时间:2024/05/15 17:04

Leo has a grid with N rows and M columns. All cells are painted with either black or white initially.

Two cells A and B are called connected if they share an edge and they are in the same color, or there exists a cell C connected to both A and B.

Leo wants to paint the grid with the same color. He can make it done in multiple steps. At each step Leo can choose a cell and flip the color (from black to white or from white to black) of all cells connected to it. Leo wants to know the minimum number of steps he needs to make all cells in the same color.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains two integers N and M (1 <= NM <= 40). Then N lines follow. Each line contains a string with N characters. Each character is either 'X' (black) or 'O' (white) indicates the initial color of the cells.

Output

For each test case, output the minimum steps needed to make all cells in the same color.

Sample Input
22 2OXOX3 3XOXOXOXOX
Sample Output
12
Hint

For the second sample, one optimal solution is:

Step 1. flip (2, 2)

XOXOOOXOX

Step 2. flip (1, 2)

XXXXXX

XXX

DFS将连通图染色转换成点与点之间的关系,然后BFS或者最短路算法求图中每点到其他点的最大距离中的最小距离就是最小反转次数。

#include <bits/stdc++.h>#define mst(a) memset(a,0,sizeof (a))#define INF 1e9 #define FOR(i,n) for (int i = 0; i < n; i++)#define eps 1e-10using namespace std;typedef long long ll;struct node{    int v,len;  //终点、长度     node(int a,int b){        v = a,len = b;    }};vector <node> tree[2222];int d[2222];  //用于记录x点到各点的距离 string s[110];int vis[110][110];int n,m;int g[110][110];int cur;bool check(int a,int b)   //检查重边,重边太多会有很多无意义的计算,导致超时 {    for (int i = 0; i < tree[a].size(); i++)    {        if (tree[a][i].v == b) return 0;    }    return 1;}void dfs(int row,int col,char type){    if (vis[row][col])    {    if(s[row][col]!=type)            if (g[row][col] && check(g[row][col],cur))  //如果下一个和这个不一样就建立一条边             {                node tmp(g[row][col],1);  //起点、长度                 tree[cur].push_back(tmp);                               tmp.v = cur;                tree[g[row][col]].push_back(tmp);            }         return;    }    if (s[row][col] == type)    {        vis[row][col] = 1;        g[row][col] = cur;        if (row > 1)dfs(row - 1,col,type);        if (row < n)dfs(row + 1,col,type);        if (col > 1)dfs(row,col - 1,type);        if (col < m)dfs(row,col + 1,type);    }}void SPFA(int x)  //x为起点{    //tree为邻接链表     int v[2222];    memset(v,0,sizeof(v));    queue<int>q;    q.push(x);    v[x] = 1;d[x] = 0;    while(!q.empty())    {        int nod = q.front();        q.pop();        v[nod] = 0;        for(int i = 0;i < tree[nod].size();i++)        {            int nxtnod = tree[nod][i].v;            if(d[nxtnod] > d[nod] + tree[nod][i].len)            {                d[nxtnod] = d[nod] + tree[nod][i].len;                if(!v[nxtnod])                {                    v[nxtnod] = 1;                    q.push(nxtnod);                }            }        }    }}int main(){    int t;    cin >> t;    while(t--)    {        memset(vis,0,sizeof(vis));        memset(g,0,sizeof(g));        for (int i = 0; i < 50; i++) s[i].clear();        for (int i = 0; i < 2000; i++) tree[i].clear();        cur = 1;        cin >> n >> m;        for (int i = 1; i <= n; i++) cin >> s[i],s[i] = " " + s[i];        for (int i = 1; i <= n; i++)        {            for (int j = 1; j <= m; j++)            {                if (!vis[i][j])                {                    dfs(i,j,s[i][j]);                    cur++;                }            }        }        int ans = INF;         for (int i = 1; i < cur; i++)  //遍历起点         {            memset(d,1,sizeof(d));  //初始化为INF            SPFA(i);            int ret = 0;            for (int j = 1; j < cur; j++)            {                ret = max(d[j],ret);            }            ans = min(ret,ans);        }        cout << ans << endl;    }     return 0;}


0 0
原创粉丝点击