【C ++】「One Book 1.1例3」散水装置(水草)

【出典】

一般的な質問バンク
-1424 UVA-10382
LibreOJ-10002
Kattis-grass
vjudge

各質問バンクの質問は同じ意味ですが、入力形式とデータ範囲が少し異なります。

【タイトル説明】

長い L L メートル、ワイド W W メーターの芝生がいっぱい 灌漑スプリンクラー。各ノズルは芝生の中心線上に設置されています(両側から) W 2 \ frac {W} {2} M)。各スプリンクラーの位置(芝生の中心線の左端からの距離)と、スプリンクラーがカバーできる散水範囲がわかっています。
ここに画像の説明を挿入

質問:芝生全体を同時に灌漑する場合、少なくともいくつのスプリンクラーを開く必要がありますか?

【入力フォーマット】

入力には、テストデータのいくつかのセットが含まれています。

最初の行の整数 T T はデータグループの数を表します。

各データセットの最初の行は整数です L n、L および W W

次のn行では、各行に2つの整数が含まれ、スプリンクラーの位置と灌漑半径を示します(上の図は、最初のデータセットのサンプル入力で説明されているケースです)。

【出力フォーマット】

テストデータのセットごとに数値が出力され、芝生全体を灌漑するために必要なスプリンクラーの最小数が示されます。すべてのスプリンクラーがオンになっていて、芝生全体に水をやることができない場合、出力 1 −1

【入力例】

3
8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1

【出力例】

6
2
-1

【データ範囲】

100%データの場合、n≤15000。

【分析】

貪欲。

スプレーヘッドによってスプレーされる水の有効範囲を見つけ、芝生の幅よりもスプレーの直径が小さいスプレーヘッドをフィルターで除去します。

次に、この問題は、間隔のフルカバレッジ問題に変換できます。 メートル メートル 間隔、次に ラインセグメントの始点と終点(これは閉じた間隔であることに注意してください)間隔全体を完全にカバーするための最小数のラインセグメントを見つけます。

各セクションを左端のポイントの昇順で配置します。ここでの貪欲な戦略は、完全にカバーされるまで、選択可能な線分の最大の右端のポイントを毎回選択することです。

【コード】

Yitongtong / LibreOJ:

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;

typedef long long LL;

const int N=15005;

struct Node {
    double l,r;

    bool operator < (const Node &rhs) const {
        return l<rhs.l;
    }
} a[N];

int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        int n,L,W;
        scanf("%d%d%d",&n,&L,&W);
        int cnt=0;
        for(int i=1; i<=n; i++) {
            int x,r;
            scanf("%d%d",&x,&r);
            if(r<W/2.0) continue;
            double tmp=sqrt(r*r-W*W/4.0);
            a[++cnt].l=1.0*x-tmp;
            a[cnt].r=1.0*x+tmp;
        }
        sort(a+1,a+cnt+1);
        double t=0;
        int ans=0,i=1,flag=0;
        while(t<L) {
            ans++;
            double s=t;
            while(a[i].l<=s && i<=cnt) {
                if(t<a[i].r) t=a[i].r;
                i++;
            }
            if(t==s && s<L) {
                printf("-1\n");
                flag=1;
                break;
            }
        }
        if(!flag) printf("%d\n",ans);
    }
    return 0;
}

UVA / Kattis:
//注:UVAに入力する変数の型は浮動小数点を使用する必要があります

#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;

typedef long long LL;

const int N=1e4+5;

struct Node {
    double l,r;

    bool operator < (const Node &rhs) const {
        return l<rhs.l;
    }
} a[N];

int main() {
    int n,L;
    double W;
    while(~scanf("%d%d%lf",&n,&L,&W)) {
        int cnt=0;
        for(int i=1; i<=n; i++) {
            double x,r;
            scanf("%lf%lf",&x,&r);
            if(r<W/2) continue;
            double tmp=sqrt(r*r-W*W/4);
            a[++cnt].l=x-tmp;
            a[cnt].r=x+tmp;
        }
        sort(a+1,a+cnt+1);
        double t=0;
        int ans=0,i=1,flag=0;
        while(t<L) {
            ans++;
            double s=t;
            while(a[i].l<=s && i<=cnt) {
                if(t<a[i].r) t=a[i].r;
                i++;
            }
            if(t==s && s<L) {
                printf("-1\n");
                flag=1;
                break;
            }
        }
        if(!flag) printf("%d\n",ans);
    }
    return 0;
}
元の記事を106件公開 156 件を賞賛 40,000回以上の閲覧

おすすめ

転載: blog.csdn.net/Ljnoit/article/details/105342029