计算机程序设计竞赛艺术(单调栈扩展)

本文介绍了一个算法问题,即给定一个n*m的矩阵和多个询问,判断是否存在全为0的子矩阵。通过预处理所有符合条件的子矩阵并使用标记数组记录,实现了在O(1)时间内回答每个查询。
计算机程序设计竞赛艺术
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 9 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →

Problem Description

Viewer discretion is advised. The following problem is very academic and that should not be understood by anyone.
An undirected graph is a graph in which the nodes are connected by undirected arcs.
An undirected arc is an edge that has no direction. Both ends of an undirected arc are equivalent. We denote an undirected arc between node A and B as A-B.
A directed graph is a graph in which the nodes are connected by directed arcs.
A directed arc is an edge that has direction. One of the endpoints of a directed arc is called the head endpoint and the other is called tail endpoint. We denote a directed arc between node A and B As A->B, in which A is head endpoint and B is the tail endpoint.
For a node, the number of head endpoints adjacent to a node is called the indegree of the node.
An orientation of an undirected graph is a transformation which turns the graph into a directed graph by assigning each arc a direction. We notate the original undirected graph as G:=(V,E) and the transformed directed graph as G':=(v',E').
A transitive orientation of an undirected graph is an orientation which satifies the following constraint:
For any three distinct nodes A,B and C
由A->B属于E'并且B->C属于E'推出A->C属于E'.
An undirected graph is called a comparability graph iff it has a transitive orientation.
It was proved in 1962 that a graph is a comparability graph iff it does not contain a 2-chordless odd cycle.
In 1977 an algorithm was designed to check if a given graph is comparability graph with complexity O(d*|E|), where d is the maximum degree of nodes. And in 2000 a paper presented a new algorithm solving the same problem in O(|E|*log2|V|). Both algorithm return a transitive orientation of the inputted graph if it is found to be comparability graph.
A complete graph is an undirected graph in which each pair of nodes is connected by an edge. It is trivial that all complete graphs are comparability graphs, because complete graths never contain chordless cycle.
ICTOP(indegree-constrained-transitive-orientation-problem) is to find a transitive orientation of an undirected graph under the upper-bound indegree of each node. In the case that such orientation doesn't exist, the problem aims at finding the transitive orientation which maximize the number of nodes whose indegree doesn't exceed the corresponding upper-bound. In the case that no transitive orientation exists, the problem aims at outputting "Oops" in a single line.
However, here comes the problem.
Z is so stupid that he doesn't understand the above bullshit at all. To spare his professional time on the contest, he decides to draw pictures on the test paper.
As you can see, the test paper is full of bullshit and there's just too little room left for painting arts. Z wonders if he could have enough room for an X*Y size painting. To generalize the problem, he divides the test paper into N*M grids. Each grid is either empty or occupied. He wonders if there's an X*Y sub-grid which contains no occupied grid. Can you help him?

Input

First line of the input contains a positive integer, indicating the number of test cases.
Each test case starts with a line containing 2 integers N and M(1<=N,M<=1000)
The next N lines each contain M integers. Each integer is either 0, which means the corresponding grid is empty, or 1, which means it's occupied.
Next line is an integer K(K<=1000000), indicating the number of Z's queries.
Each of the next K lines contains two integers A and B, which means Z wonders if there's an empty sub-grid fo size A*B(1<=A<=N;1<=B<=M).
Note that query is just asking question. Z will not draw anything during his query stage. So the test paper remains the same for every query in a test case.

Output

For each query, just output a line containing "Y" if the corresponding empty A*B sub-grid can be found, or "N" otherwise.

Sample Input

1
3 3
1 1 1
0 0 0
1 0 0
5
1 1
1 3
3 1
2 2
2 3

Sample Output

Y
Y
N
Y
N

Author

HYNU
 
题目说了一大堆,其实主要就是后面的有用,给定一个n*m的矩阵和k个询问,问是否存在一个全为0的子矩阵。是输出Y,否则输出N。
思路是预处理出所有满足条件的子矩阵,然后查询的时候就可以在O(1)时间得出,预处理跟最大矩形那题类似,也是枚举每一行,每行上方就是一个最大矩形问题,然后不用更新最大值,只是用一个标记数组把把这个矩形标记为1即可,表示这个矩形存在,这样处理完后只是得出了大矩形的位置,但是还需要更新小的矩形,这样在枚举完后我单独用了两重循环遍历,把隐藏的求出来,就可以查询了。
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int N = 1000 + 10;
int flag[N][N],map[N][N],f[N],ff[N];
void solve(int ff[],int m)
{
    stack<int>s;
    int i,l,k,temp;
    ff[m+1]=-1;
    for(i=1;i<=m+1;i++)
    {
        if(s.empty()||ff[i]>ff[s.top()])
        {
            s.push(i);
        }
        else if(ff[i]<ff[s.top()])
        {
            while(!s.empty()&&ff[i]<ff[s.top()])
            {
            flag[ff[s.top()]][i-s.top()]=1;
            //printf("%d %d\n",ff[s.top()],i-s.top());
            temp=s.top();
            s.pop();
            }
        s.push(temp);
        ff[temp]=ff[i];
        }
    }
}
int main()
{
    //freopen("a.txt","r",stdin);
    int t,n,m,k,a,b,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            scanf("%d",&map[i][j]);
        memset(flag,0,sizeof(flag));
        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
                if(map[i][j]==0) f[j]++;
                else f[j]=0;

            memcpy(ff,f,sizeof(f));
            solve(ff,m);
        }
        /*for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
                printf("%d ",flag[i][j]);
            printf("\n");
        }*/
        for(i=n;i>=1;i--)  //遍历出小的矩形,并且是从后往前,一步步求出。
        {
            for(j=m;j>=1;j--)
                flag[i][j]=flag[i][j]||flag[i+1][j]||flag[i][j+1];
        }
        scanf("%d",&k);
        while(k--)
        {
            scanf("%d%d",&a,&b);
            if(flag[a][b]) printf("Y\n");
            else printf("N\n");
        }
    }
    return 0;
}

 
 
国际程序设计大赛的作品欣赏 1、 先来第一个: 一段纯 3D 的 DOS 动画,据说是获一等奖的作品。虽然它不是最精美的, 但是当你得知它只有 4K 时,会不会立刻疯死掉呢? 附件:3ddemo.com 2、 再来一个: 幽灵古堡 farb-rausche 64.0 KB (65,536 字节) 恰好 65536 字节,显然是参赛作品。它非常漂亮(利用了 Direct3D),更让人惊奇的是只有 64K!而更让人震惊的是,如果不压缩的话它的数据大小是 1.6G!再体会一次“奇迹”! 附件:castle.exe 3、 再来一个: 死亡阴影 64.0 KB (65,536 字节) 附件:death.exe 4、 火域幻境 73.0 KB (74,752 字节) 虽然大小超过了 64K 的限制,但是它的效果可称为程序中的艺术品了! 附件:fire.exe 5、 fr-016 farb-rausche 16 字节 (16 字节) Let's rock hard!一个 DOS 里的小动画。看上去似乎没有什么特别,但是如果看到它的大小(16 字节),什么感觉????? 附件:fr-016.com 6、 第七天堂 Exceed 64.0 KB (65,536 字节) 由于参赛的要求是在 64K 之内即可,不少参赛者未免会有不到 65536 字节就有吃亏的感觉。 这是个 恰好 64K 的作品,可能利用了 DirectX 引擎,效果很好。 附件:heaven7.exe 7、 金属迷城 6.00 KB (6,144 字节) 考虑到它的大小时,你会不会体会到奇迹的含义 附件:metal.exe 8、 我要重点推荐的是这个作品fr-041_debris.exe(177K),效果是这所有作品之中最好的,一般的电脑无法流畅运行,我认为你买电脑时 可以把它带上运行一下作为一款测试工具。 附件:fr-041_debris.exe 9、 这个作品的效果和以上作品比都可名列前矛(64K),效果很好 附件:kkino64.exe 10、 这个就是传说中的25万倍压缩作品,prophecy《彗星撞地球》(63.5K)2000年时的最经典力作!画面看着挺舒服。 附件:prophecy《彗星撞地球》.exe 11、 爱之记忆 12、 3D裸女 13、 卡通 14、 光影 15、 FAiRLiGHT 这是在《三角洲3大地勇士》光碟版中带有的一个DEMO,发行组织FAiRLiGHT完全用原代码写出的自己组织的DEMO演示程序, 竟然才15K大小,画面也还行,对于他们的技术我们只能感到折服!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值