UVA10382喷水装置
生活随笔
收集整理的這篇文章主要介紹了
UVA10382喷水装置
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給你一個矩形的空地,然后有一些圓形的噴水裝置,每個裝置的圓心都在矩形寬的中間位置,然偶給你每個矩形的圓心位置和半徑,問你最少多少個噴水裝置可以把矩形的所有編輯都覆蓋上。
思路:
? ? ? 首先我們要把所有的圓都處理成矩形,也就是每個圓的最大覆蓋矩形范圍(除了矩形的部分,其他部分沒意義,因為只有矩形能接壤上,不然會有空隙),然后變成了最小區間覆蓋問題,最小區間覆蓋問題可以用貪心的方式處理,剛做完UVA10020就是有一個單純的求最小區間覆蓋,那個題解剛寫完,我直接把那個題解粘貼過來吧:
? ? 大體思路可以是這樣,我們先把所有的區間按照起點從小到大排序,然后我們定義一個當前覆蓋位置pos,初始是0,也就是[0,m]的最左端,然后我們從小區間中找到一個可以覆蓋pos點并且右端點最遠的一個(記得sum++),然后把最遠的這個右端點作為當前的pos,繼續找下一個,至于實現,我是自己寫的,可能寫的不是很簡潔,不知道網上有沒有簡潔點的,如果沒有就講究看下我的吧,具體細節看代碼。
#include<math.h>
#include<stdio.h>
#include<algorithm>
#define N 11000
typedef struct
{
? ?double l ,r;
}EDGE;
EDGE edge[N];
bool camp(EDGE a ,EDGE b)
{
? ?return a.l < b.l;
}
int main ()
{
? ?int n ,l ,w ,i;
? ?double x ,r;
? ?while(~scanf("%d %d %d" ,&n ,&l ,&w))
? ?{
? ? ? double w2 = w * 1.0 / 2;
? ? ? int nowid = 0;
? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? {
? ? ? ? ?scanf("%lf %lf" ,&x ,&r);
? ? ? ? ?if(r <= w2) continue;
? ? ? ? ?double tmp = sqrt(r * r - w2 * w2);
? ? ? ? ?double ll = x - tmp ,rr = x + tmp;
? ? ? ? ?if(rr < 0 || ll > l) continue;
? ? ? ? ?nowid ++;
? ? ? ? ?edge[nowid].l = ll ,edge[nowid].r = rr;
? ? ? }
? ? ? sort(edge + 1 ,edge + nowid + 1 ,camp);
? ? ? int Ans = 0;
? ? ? double pos = 0 ,max = 0;
? ? ? for(i = 1 ;i <= nowid ;i ++)
? ? ? {
? ? ? ? ?if(pos > edge[i].r) continue; ?
? ? ? ? ?if(edge[i].l <= pos)
? ? ? ? ?{
? ? ? ? ? ? if(max < edge[i].r) max = edge[i].r;
? ? ? ? ? ? if(i == nowid)
? ? ? ? ? ? {
? ? ? ? ? ? ? ?if(max < l){Ans = -1 ;break;}
? ? ? ? ? ? ? ?Ans ++;
? ? ? ? ? ? }
? ? ? ? ?}
? ? ? ? ?else
? ? ? ? ?{
? ? ? ? ? ? if(max == 0){Ans = -1 ;break;}
? ? ? ? ? ? pos = max;
? ? ? ? ? ? if(pos >= l) break;
? ? ? ? ? ? max = 0 ,Ans ++ ,i --;
? ? ? ? ?}
? ? ? }
? ? ? if(!Ans) Ans = -1;?
? ? ? printf("%d\n" ,Ans);
? ?}
? ?return 0;
}
? ? ? ? ?
? ? ? ? ??
? ? ? 給你一個矩形的空地,然后有一些圓形的噴水裝置,每個裝置的圓心都在矩形寬的中間位置,然偶給你每個矩形的圓心位置和半徑,問你最少多少個噴水裝置可以把矩形的所有編輯都覆蓋上。
思路:
? ? ? 首先我們要把所有的圓都處理成矩形,也就是每個圓的最大覆蓋矩形范圍(除了矩形的部分,其他部分沒意義,因為只有矩形能接壤上,不然會有空隙),然后變成了最小區間覆蓋問題,最小區間覆蓋問題可以用貪心的方式處理,剛做完UVA10020就是有一個單純的求最小區間覆蓋,那個題解剛寫完,我直接把那個題解粘貼過來吧:
? ? 大體思路可以是這樣,我們先把所有的區間按照起點從小到大排序,然后我們定義一個當前覆蓋位置pos,初始是0,也就是[0,m]的最左端,然后我們從小區間中找到一個可以覆蓋pos點并且右端點最遠的一個(記得sum++),然后把最遠的這個右端點作為當前的pos,繼續找下一個,至于實現,我是自己寫的,可能寫的不是很簡潔,不知道網上有沒有簡潔點的,如果沒有就講究看下我的吧,具體細節看代碼。
#include<math.h>
#include<stdio.h>
#include<algorithm>
#define N 11000
using namespace std;
typedef struct
{
? ?double l ,r;
}EDGE;
EDGE edge[N];
bool camp(EDGE a ,EDGE b)
{
? ?return a.l < b.l;
}
int main ()
{
? ?int n ,l ,w ,i;
? ?double x ,r;
? ?while(~scanf("%d %d %d" ,&n ,&l ,&w))
? ?{
? ? ? double w2 = w * 1.0 / 2;
? ? ? int nowid = 0;
? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? {
? ? ? ? ?scanf("%lf %lf" ,&x ,&r);
? ? ? ? ?if(r <= w2) continue;
? ? ? ? ?double tmp = sqrt(r * r - w2 * w2);
? ? ? ? ?double ll = x - tmp ,rr = x + tmp;
? ? ? ? ?if(rr < 0 || ll > l) continue;
? ? ? ? ?nowid ++;
? ? ? ? ?edge[nowid].l = ll ,edge[nowid].r = rr;
? ? ? }
? ? ? sort(edge + 1 ,edge + nowid + 1 ,camp);
? ? ? int Ans = 0;
? ? ? double pos = 0 ,max = 0;
? ? ? for(i = 1 ;i <= nowid ;i ++)
? ? ? {
? ? ? ? ?if(pos > edge[i].r) continue; ?
? ? ? ? ?if(edge[i].l <= pos)
? ? ? ? ?{
? ? ? ? ? ? if(max < edge[i].r) max = edge[i].r;
? ? ? ? ? ? if(i == nowid)
? ? ? ? ? ? {
? ? ? ? ? ? ? ?if(max < l){Ans = -1 ;break;}
? ? ? ? ? ? ? ?Ans ++;
? ? ? ? ? ? }
? ? ? ? ?}
? ? ? ? ?else
? ? ? ? ?{
? ? ? ? ? ? if(max == 0){Ans = -1 ;break;}
? ? ? ? ? ? pos = max;
? ? ? ? ? ? if(pos >= l) break;
? ? ? ? ? ? max = 0 ,Ans ++ ,i --;
? ? ? ? ?}
? ? ? }
? ? ? if(!Ans) Ans = -1;?
? ? ? printf("%d\n" ,Ans);
? ?}
? ?return 0;
}
? ? ? ? ?
? ? ? ? ??
總結
以上是生活随笔為你收集整理的UVA10382喷水装置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UVA10020(最小区间覆盖)
- 下一篇: UVA10340子序列