|
|
| ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
| ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
| If window 4 were then brought to the foreground: |
|
Unfortunately, Boudreaux's computer is very unreliable and crashes often. He could easily tell if a crash occurred by looking at the windows and seeing a graphical representation that should not occur if windows were being brought to the foreground correctly. And this is where you come in . . .
A single data set has 3 components:
- Start line - A single line:
START
- Screen Shot - Four lines that represent the current graphical representation of the windows on Boudreaux's screen. Each position in this 4 x 4 matrix will represent the current piece of window showing in each square. To make input easier, the list of numbers on each line will be delimited by a single space.
- End line - A single line:
END
After the last data set, there will be a single line:
ENDOFINPUT
Note that each piece of visible window will appear only in screen areas where the window could appear when brought to the front. For instance, a 1 can only appear in the top left quadrant.
THESE WINDOWS ARE CLEAN
Otherwise, the output will be a single line with the statement:
THESE WINDOWS ARE BROKEN
START 1 2 3 3 4 5 6 6 7 8 9 9 7 8 9 9 END START 1 1 3 3 4 1 3 3 7 7 9 9 7 7 9 9 END ENDOFINPUT
THESE WINDOWS ARE CLEAN THESE WINDOWS ARE BROKEN
题意:
给你一个4*4的棋盘窗口,现在电脑上有9个应用,每个应用占用固定的2*2正方形网格位置.你通过不同的顺序操作9个应用可以使得4*4的窗口当前显示的内容(数字代表)不同,现在给你一个4*4棋盘窗口的内容,问你这个内容是否合法.
思路:
一开始看到该题目时,一脸懵,不知从何下手,看了饶齐的博客之后才知道,还有这种操作》》,唉,见的题目太少了,其实就是拓扑排序,关键是将问题转换成图的拓扑排序。
其实本题就是一个判定拓扑排序是否存在的问题.把9个小窗口应用看成9个点,然后对于4*4的棋盘来说:
你看(1,2)这个方格当前放的是2数字,原本(1,2)方格我们能放的数有1和2两个数,现在放了2,说明从1应用->2应用有一条有向边.(也即是说应用1应先放,应用2后放,所以应用2能遮盖应用1).现在来看(2,2)这个方格,这个方格是5,但是这个方格原先能放的应用有:1,2,4,5 四个应用.现在出现的应用是5,说明5是最后才放的应用.所以我们可知从应用1->5应用有一条有向边,从2->5,4->5都有一条有向边. 然后我们通过分析所有的4*4格子就能得到所有的有向边,得到G[10][10]数组和in[10]数组.
这题还要注意,我们假设:如果(1,2)格子只能显示1或2,那么它就不可能显示3,4,5等数字. 输入中不会有这种数据.
注意:源代码中实现是应用0-8数字表示,且棋盘4*4也是从0开始计数的.程序中可能会重复添加有向边,一定要先判断当前G[i][j]是否==0.参考:点击打开链接
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=10;
vector<int> value[maxn][maxn];
int dr[]={0,1,0,1}; //方向的判断
int dc[]={0,0,1,1};
int G[maxn][maxn]; //图
int in[maxn]; //入度
bool topo()
{
queue<int> Q;
for(int i=0;i<9;i++)
if(in[i]==0)
Q.push(i);
int sum=0; //记录删除的0入度的点
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for(int v=0;v<9;v++)if(G[u][v]) //和模板小小区别
{
G[u][v]=0;
if(--in[v]==0)
Q.push(v);
}
sum++;
}
return sum==9;
}
int main()
{
for(int i=0;i<9;i++) //处理0-8每个应用所在方格
{
int r=i/3, c=i%3; //i应用所在左上角的位置坐标
for(int dir=0;dir<4;dir++) //其余三个位置
{
int rr=r+dr[dir];
int cc=c+dc[dir];
value[rr][cc].push_back(i);
}
}
char str[100];
while(scanf("%s",str)==1&&str[0]!='E')
{
memset(G,0,sizeof(G));
memset(in,0,sizeof(in));
for(int i=0;i<4;i++) //重要的处理成图的过程
for(int j=0;j<4;j++)
{
int v;
scanf("%d",&v);
v--;
for(int k=0; k<value[i][j].size(); k++)
if((value[i][j])[k]!=v)
{
int x=(value[i][j])[k];
if(G[x][v]==0)
{
in[v]++;
G[x][v]=1;
}
}
}
if(topo())
printf("THESE WINDOWS ARE CLEAN\n");
else
printf("THESE WINDOWS ARE BROKEN\n");
scanf("%s",str);
}
return 0;
}
地址:
点击打开链接