POJ--2585--Window Pains【拓扑排序】

链接:http://poj.org/problem?id=2585

题意:有一个4*4的屏幕,有9个窗口各占2*2大小,保证不会存在一个窗口完全覆盖任一个窗口,但每个窗口都会部分被其他窗口覆盖(因为4*4和2*2 = =、)现在需要你判断电脑是否死机。(死机的话会出现无法判断A覆盖B还是B覆盖A的情况)

思路:无法判断A覆盖B还是B覆盖A,可以当做是图中A和B之间存在环,我们可以把每个窗口当做一个顶点,如果A覆盖了B,就以A为起点、B为终点连一条有向边,这样建完图之后入度为0的点就是没有没覆盖的窗口,然后进行拓扑排序,相当于每次关闭掉一个没有被覆盖的窗口,如果最后所有窗口都能被关闭,说明没有死机,否则(即存在环)说明死机。

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 50100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define LLINF 0x7FFFFFFFFFFFFFFF
#define seed 131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct node{
    int u,v,next;
}edge[MAXN];
int head[20],vis[20],in[20],mapp[10][10];
int n,cnt;
string win[20] = {"1","12","23","3","14","1245","2356","36","47","4578","5689","69","7","78","89","9"};
void add_edge(int a,int b){
    edge[cnt].u = a;
    edge[cnt].v = b;
    edge[cnt].next = head[a];
    head[a] = cnt++;
}
void build_graph(){
    int i,j;
    int tot = 0;
    for(i=1;i<=4;i++){
        for(j=1;j<=4;j++){
            for(int ii=0;ii<win[tot].length();ii++){
                if(win[tot][ii]-'0'==mapp[i][j])    continue;
                if(vis[win[tot][ii]-'0']){
                    in[win[tot][ii]-'0']++;
                    add_edge(mapp[i][j],win[tot][ii]-'0');
                }
            }
            tot++;
        }
    }
}
bool toposort(){
    int i;
    queue<int>q;
    for(i=1;i<10;i++){
        if(!in[i]&&vis[i]) q.push(i);
    }
    int sum = 0;
    while(!q.empty()){
        int u = q.front();
        q.pop();
        sum++;
        for(i=head[u];i!=-1;i=edge[i].next){
            int next = edge[i].v;
            in[next]--;
            if(in[next] == 0)   q.push(next);
        }
    }
    if(sum==n)  return true;
    return false;
}
int main(){
    int i,j;
    char str[20];
    while(scanf("%s",str),strlen(str)<6){
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(in,0,sizeof(in));
        n = cnt = 0;
        for(i=1;i<=4;i++){
            for(j=1;j<=4;j++){
                scanf("%d",&mapp[i][j]);
                if(!vis[mapp[i][j]])    n++;
                vis[mapp[i][j]] = 1;
            }
        }
        scanf("%s",str);
        build_graph();
        if(toposort())  printf("THESE WINDOWS ARE CLEAN\n");
        else    printf("THESE WINDOWS ARE BROKEN\n");
    }
    return 0;
}
时间: 2024-11-12 08:45:52

POJ--2585--Window Pains【拓扑排序】的相关文章

poj 2585 Window Pains(拓扑排序)(经典)(困难)

Window Pains Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1756   Accepted: 881 Description Boudreaux likes to multitask, especially when it comes to using his computer. Never satisfied with just running one application at a time, he u

POJ 2585 Window Pains 拓扑排序

poj2585 题意: 有一块4X4的屏幕   屏幕中共有9块固定位置的2X2窗口(相互覆盖)  问窗口是否全部显示正常 题解: 判断所有位置的覆盖情况 如果a覆盖b 则构造一条边edge[b][a]=1    最后得到一个图 这个图一定是无环的   如果有环则表示a覆盖b   b又覆盖a 即显示不正常 代码: #include<cstdio> #include<cstring> #include<iostream> using namespace std; int m

POJ 2585 Window Pains(拓扑排序&#183;窗口覆盖)

题意  有一个4*4的显示器  有9个程序  每个程序占2*2个格子  他们的位置如图所示  当你运行某个程序时  这个程序就会显示在顶层覆盖其它的程序  给你某个时刻显示器的截图  判断此时电脑是否死机了(出现了不合法的覆盖关系) 拓扑排序的应用  关键是建图  当一个程序A的区域上有其它程序B时  说明A是在B之前运行的  那么我们可以建立一个A<B的拓扑关系  最后判断是否有环就行了  个人认为下标换为0操作起来比较方便  所以都还为了0 #include <cstdio> #in

poj 2585 Window Pains 解题报告

Window Pains Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2027   Accepted: 1025 Description Boudreaux likes to multitask, especially when it comes to using his computer. Never satisfied with just running one application at a time, he

POJ 2585.Window Pains

Window Pains Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1888   Accepted: 944 Description Boudreaux likes to multitask, especially when it comes to using his computer. Never satisfied with just running one application at a time, he u

zoj 2193 poj 2585 Window Pains

拓扑排序. 深刻体会:ACM比赛的精髓之处不在于学了某个算法或数据结构,而在于知道这个知识点但不知道这个问题可以用这个知识去解决!一看题目,根本想不到是拓扑排序.T_T...... #include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<algorithm> using namespace std; int mapp[50][50]; char

poj 2585 Window Pains 暴力枚举排列

题意: 在4*4的格子中有9个窗体,窗体会覆盖它之下的窗体,问是否存在一个窗体放置的顺序使得最后的结果与输入同样. 分析: 在数据规模较小且不须要剪枝的情况下能够暴力(思路清晰代码简单),暴力一般分为枚举子集(for(s=0;s<1<<n;++s))和枚举排列(next_permutation). 代码: //poj 2585 //sep9 #include <iostream> #include <algorithm> using namespace std;

POJ 2585 Window Pains 题解

链接:http://poj.org/problem?id=2585 题意: 某个人有一个屏幕大小为4*4的电脑,他很喜欢打开窗口,他肯定打开9个窗口,每个窗口大小2*2.并且每个窗口肯定在固定的位置上(见题目上的图),某些窗口可以覆盖另一些窗口(可以脑补).询问给出的电脑屏幕是否是合法的. 分析: 可以预先处理出每个格子应该有哪几个窗口在这上面,将最上面的窗口与其他窗口连边,得到一张图,用拓扑判环,因为这道题太简单了,所以我就写这么短的题解. 代码: 1 #include<iostream>

poj 1270 Following Orders(拓扑排序+dfs)

大致题意:每个样例包含两行,第一行输入n个字符,可能是无序的.第二行输入成对的a b,代表a要在b前面.输出所有的符合这样的序列. 思路:很明显的拓扑排序.要输出所有的序列,那么就从入度为0的点进行dfs,每次选择一个入度为0的点,加入输出序列并把与它相邻的点的入度减一.dfs结束后要把状态再改回来. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include

[ACM] POJ 3687 Labeling Balls (拓扑排序,逆向建边)

Labeling Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10161   Accepted: 2810 Description Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that: No two balls share