P5995 [PA2014] Lustra

提供一种极易理解的纯模拟做法。

虽然时空都不是很优秀,但是距离时空超限还绰绰有余。并且没有运用什么深奥的算法与技巧,非常适合算法初学者,并且还留有极大的优化空间。

理解题意,题目要求我们求出是否有工厂可以生产其他所有工厂的镜子,为满足这个要求,那么符合条件的工厂的 $w1,w2,h1,h2$ 一定是最小的。所以可将问题转化为求所有数据中 $w1,w2,h1,h2$ 四个数的最小值,是否在同一工厂。

  • 易错点:

Q:

那么不是在输入的时候将 $w1,w2,h1,h2$ 四个数的最小值,分别记录,并且记录下它们的下标就可以了吗?这不就是在一串数中找最大、最小值的位置吗?然后,如果 $w1,w2,h1,h2$ 四个数的最小值的下标都一样,就输出 TAK 否则输出 NIE

A:

其实不然,请看数据(在 $n=4$ 时):

1 5 2 3
2 3 2 6
1 5 1 6
1 5 1 4

$w1,w2$ 的最小值都存在于第一家工厂、第三家工厂和最后一家工厂中。但是一般性的查询 $w1,w2$ 两个数的最大、最小值的下标都会记录第一家工厂或最后一家工厂。然后程序就会发现 $h1,h2$ 两个数的最大、最小值的下标不在第一家工厂,与最后一家工厂,从而输出 NIE。但答案确是 TAK

如何解决这种情况呢?我们可以将输入进来的 $w1,w2,h1,h2$ 四个数与前边已经计算好的 $w1,w2,h1,h2$ 的最大、最小值比较,如果等于最大、最小值,就将其加入标记数组中,代表这家工厂有可能有能力生产其他所有工厂的镜子。如果大于、小于最大、最小值,就见最大、最小值跟换,并清空标记数组。

这一部分的代码实现。

if(w1<=minw1){
    if(w1==minw1) fw1[i]=1;
    else {
        minw1=w1;
        memset(fw1,0,sizeof fw1);
        fw1[i]=1;
    }
}

整体代码实现:

#include<bits/stdc++.h>
using namespace std;
int T,n;
int minw1,maxw2,minh1,maxh2;
bool fw1[100001],fw2[100001],fh1[100001],fh2[100001];
int main(){
    cin>>T;
    while(T--){
        minw1=minh1=10e9+1;
        maxw2=maxh2=-1;
        int a,b,c,d;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a>>b>>c>>d;
            //这一部分已讲解,不再添加注释。
            if(a<=minw1){
                if(a==minw1) fw1[i]=1;
                else {
                    minw1=a;
                    memset(fw1,0,sizeof fw1);
                    fw1[i]=1;
                }
            }
            if(b>=maxw2){
                if(b==maxw2) fw2[i]=1;
                else {
                    maxw2=b;
                    memset(fw2,0,sizeof fw2);
                    fw2[i]=1;
                }
            }
            if(c<=minh1){
                if(c==minh1) fh1[i]=1;
                else {
                    minh1=c;
                    memset(fh1,0,sizeof fh1);
                    fh1[i]=1;
                }
            }
            if(d>=maxh2){
                if(d==maxh2) fh2[i]=1;
                else {
                    maxh2=d;
                    memset(fh2,0,sizeof fh2);
                    fh2[i]=1;
                }
            }
        }
        //遍历 n 家工厂,如果某家工厂四个数值都符合条件,输出 TAK。
        bool flag=1;
        for(int i=1;i<=n;i++){
            if(fw1[i]&&fw2[i]&&fh1[i]&&fh2[i]){
                cout<<"TAK"<<'\n';
                flag=0;
                break;
            }
        }
        if(flag) cout<<"NIE"<<'\n';
        memset(fh2,0,sizeof fh2);
        memset(fh1,0,sizeof fh1);
        memset(fw2,0,sizeof fw2);
        memset(fw1,0,sizeof fw1);
    }
    return 0;
}
posted @ 2023-07-04 13:08  shoot_down  阅读(32)  评论(0)    收藏  举报  来源