感觉是一种很有用的思路,就是判断一系列操作的顺序。这个问题能够转换成拓扑排序的关键在于,每种颜色仅会被用到一次。
对于这个问题,如果能够包围颜色A的最小矩形里有颜色B,那么颜色B应该在颜色A之后绘制。根据这个就可以建立一个拓扑关系图。
要说代码上的细节倒也没有什么,主要是思路想到就好办了。
class Solution {
public:
bool isPrintable(vector<vector<int>>& targetGrid) {
map<int,int> bound[4];//上左下右
int m=targetGrid.size(),n=targetGrid[0].size();
for(int i=0;i<m;++i)
for(int j=0;j<n;++j)
{
if(!bound[0].count(targetGrid[i][j]))
bound[0][targetGrid[i][j]]=i;
bound[2][targetGrid[i][j]]=i;
if(!bound[1].count(targetGrid[i][j])||bound[1][targetGrid[i][j]]>j)
bound[1][targetGrid[i][j]]=j;
if(!bound[3].count(targetGrid[i][j])||bound[3][targetGrid[i][j]]<j)
bound[3][targetGrid[i][j]]=j;
}
bool link[61][61];
memset(link,0,sizeof(link));
for(int c=1;c<=60;++c)if(bound[0].count(c))
{
for(int i=bound[0][c];i<=bound[2][c];++i)
{
for(int j=bound[1][c];j<=bound[3][c];++j)
{
if(targetGrid[i][j]!=c)
{
link[targetGrid[i][j]][c]=true;
}
}
}
}
int index[61]={
0};
for(int i=1;i<=60;++i)
for(int j=1;j<=60;++j)
if(link[i][j])
++index[j];
bool vis[61]={
0};
int visCount=0;
for(int t=0;t<60;++t)
{
bool flag=true;
for(int i=1;i<=60;++i)if(index[i]==0&&!vis[i])
{
flag=false;
vis[i]=true;
++visCount;
for(int j=1;j<=60;++j)
{
if(link[i][j])
--index[j];
}
}
if(visCount==60)
return true;
if(flag)
return false;
}
return true;
}
};