100917A - Abstract Picture Gym (思维)
作者:互联网
【题解】
题意:给每一行和每一列精准涂色,给定最后的颜色分布,'?'表示随意,请输出任意一种涂色方案。
思路:从只有一种确定颜色的行和列往回推,一步步撤销涂上的颜色,用类似拓扑排序的方法每次找到只有一种确定颜色或全随意的行和列进行涂色,最后倒序输出即可。我用结构体记录行和列的颜色分布状态,用1-n表示行,用n+1-2*n表示列,在撤销涂色操作的时候不小心搞混了找了蛮久错的1551.
【代码】
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> p;
struct node{
int cou;
int vis[30];
}f[6005];
char mp[3005][3005];
int a[3005][3005];
bool is[6005];
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x=a[i][j]=mp[i][j]-'a';
if(x<0) continue; //'?'
if(!f[i].vis[x]) f[i].cou++;
f[i].vis[x]++;
if(!f[j+n].vis[x]) f[j+n].cou++;
f[j+n].vis[x]++;
}
}
stack <p> stk;
while(stk.size()<2*n){
for(int i=1;i<=2*n;i++){
if(!is[i]&&f[i].cou<=1){
is[i]=true;
if(f[i].cou==0){
stk.push(p(i,0));
continue;
}
int pos=0;
while(!f[i].vis[pos]) pos++;
stk.push(p(i,pos));
if(i<=n){ //行
for(int j=1;j<=n;j++){
if(a[i][j]==pos){
f[n+j].vis[pos]--;
if(f[n+j].vis[pos]==0)
f[n+j].cou--;
}
}
for(int j=1;j<=n;j++)
a[i][j]=-1;
}
else{ //列
for(int j=1;j<=n;j++){
if(a[j][i-n]==pos){
f[j].vis[pos]--;
if(f[j].vis[pos]==0)
f[j].cou--;
}
}
for(int j=1;j<=n;j++)
a[j][i-n]=-1;
}
}
}
}
while(!stk.empty()){
p ff=stk.top();
if(ff.first<=n){
printf("h %d %c\n",ff.first,ff.second+'a');
}
else{
printf("v %d %c\n",ff.first-n,ff.second+'a');
}
stk.pop();
}
return 0;
}
【题目】
标签:100917A,Picture,6005,颜色,int,Abstract,行和列,3005,涂色 来源: https://blog.csdn.net/qq_41117236/article/details/97421709