2020年HZNU天梯訓練賽 Round 3
2020年HZNU天梯訓練賽 Round 3
時間:2020.7.17 22 180
完成情況:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | ||||
√ 當場做出來 ※做了一半來 ✘補題補出來
7-1 到底有多二 (15分)
一個整數“犯二的程度”定義為該數字中包含2的個數與其位數的比值。如果這個數是負數,則程度增加0.5倍;如果還是個偶數,則再增加1倍。例如數字-13142223336
是個11位數,其中有3個2,並且是負數,也是偶數,則它的犯二程度計算為:3/11×1.5×2×100%,約為81.82%。本題就請你計算一個給定整數到底有多二。
輸入格式:
輸入第一行給出一個不超過50位的整數N
。
輸出格式:
在一行中輸出N
犯二的程度,保留小數點後兩位。
輸入樣例:
-13142223336
輸出樣例:
81.82%
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; typedef long long LL; int main() { char s[55]; int cnt=0,num=0,begin=0; cin>>s; double p=1; if(s[0]=='-'){p*=1.5;begin=1;} if((s[strlen(s)-1]-'0')%2==0)p*=2; for(int i=begin;i<strlen(s);i++) { if((s[i]-'0')%10==2)cnt++; num++; } //cout<<cnt<<"***"<<num<<endl; double ans=(double)cnt/(double)num*p*100; printf("%.2lf%%",ans); return 0; }
7-2 大笨鐘 (10分)
微博上有個自稱“大笨鐘V”的傢伙,每天敲鐘催促碼農們愛惜身體早點睡覺。不過由於笨鍾自己作息也不是很規律,所以敲鐘並不定時。一般敲鐘的點數是根據敲鐘時間而定的,如果正好在某個整點敲,那麼“當”數就等於那個整點數;如果過了整點,就敲下一個整點數。另外,雖然一天有24小時,鍾卻是隻在後半天敲1~12下。例如在23:00敲鐘,就是“噹噹噹噹噹噹噹噹噹噹噹”,而到了23:01就會是“噹噹噹噹噹噹噹噹噹噹噹噹”。在午夜00:00到中午12:00期間(端點時間包括在內),笨鍾是不敲的。
下面就請你寫個程式,根據當前時間替大笨鐘敲鍾。
輸入格式:
輸入第一行按照hh:mm
的格式給出當前時間。其中hh
mm
是分鐘,在00到59之間。
輸出格式:
根據當前時間替大笨鐘敲鍾,即在一行中輸出相應數量個Dang
。如果不是敲鐘期,則輸出:
Only hh:mm. Too early to Dang.
其中hh:mm
是輸入的時間。
輸入樣例1:
19:05
輸出樣例1:
DangDangDangDangDangDangDangDang
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{
int a,b;
scanf("%d:%d",&a,&b);
if(a<12||(a==12&&b==00))
{
if(a<10&&b>10)printf("Only 0%d:%d. Too early to Dang.\n",a,b);
if(a<10&&b<10)printf("Only 0%d:0%d. Too early to Dang.\n",a,b);
if(a>10&&b<10)printf("Only %d:0%d. Too early to Dang.\n",a,b);
if(a>10&&b>10)printf("Only %d:%d. Too early to Dang.\n",a,b);
}
else
{
int x;
if(b==00) {for(int i=0;i<a-12;i++)cout<<"Dang";}
else {for(int i=0;i<a-11;i++)cout<<"Dang";}
}
return 0;
}
7-3 誰先倒 (15分)
划拳是古老中國酒文化的一個有趣的組成部分。酒桌上兩人划拳的方法為:每人口中喊出一個數字,同時用手比劃出一個數字。如果誰比劃出的數字正好等於兩人喊出的數字之和,誰就輸了,輸家罰一杯酒。兩人同贏或兩人同輸則繼續下一輪,直到唯一的贏家出現。
下面給出甲、乙兩人的酒量(最多能喝多少杯不倒)和划拳記錄,請你判斷兩個人誰先倒。
輸入格式:
輸入第一行先後給出甲、乙兩人的酒量(不超過100的非負整數),以空格分隔。下一行給出一個正整數N
(≤100),隨後N
行,每行給出一輪划拳的記錄,格式為:
甲喊 甲劃 乙喊 乙劃
其中喊
是喊出的數字,劃
是劃出的數字,均為不超過100的正整數(兩隻手一起劃)。
輸出格式:
在第一行中輸出先倒下的那個人:A
代表甲,B
代表乙。第二行中輸出沒倒的那個人喝了多少杯。題目保證有一個人倒下。注意程式處理到有人倒下就終止,後面的資料不必處理。
輸入樣例:
1 1
6
8 10 9 12
5 10 5 10
3 8 5 12
12 18 1 13
4 16 12 15
15 1 1 16
輸出樣例:
A
1
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int main()
{
int a,b,n,x,y,z,w,aa,bb;
cin>>a>>b>>n;
aa=a;bb=b;
while(n--)
{
cin>>x>>y>>z>>w;
if(x+z==y&&x+z!=w)a--;
if(x+z==w&&x+z!=y)b--;
if(a==-1){cout<<"A"<<endl<<bb-b;break;}
if(b==-1){cout<<"B"<<endl<<aa-a;break;}
}
return 0;
}
7-4 帥到沒朋友 (20分)
當芸芸眾生忙著在朋友圈中發照片的時候,總有一些人因為太帥而沒有朋友。本題就要求你找出那些帥到沒有朋友的人。
輸入格式:
輸入第一行給出一個正整數N
(≤100),是已知朋友圈的個數;隨後N
行,每行首先給出一個正整數K
(≤1000),為朋友圈中的人數,然後列出一個朋友圈內的所有人——為方便起見,每人對應一個ID號,為5位數字(從00000到99999),ID間以空格分隔;之後給出一個正整數M
(≤10000),為待查詢的人數;隨後一行中列出M
個待查詢的ID,以空格分隔。
注意:沒有朋友的人可以是根本沒安裝“朋友圈”,也可以是隻有自己一個人在朋友圈的人。雖然有個別自戀狂會自己把自己反覆加進朋友圈,但題目保證所有K
超過1的朋友圈裡都至少有2個不同的人。
輸出格式:
按輸入的順序輸出那些帥到沒朋友的人。ID間用1個空格分隔,行的首尾不得有多餘空格。如果沒有人太帥,則輸出No one is handsome
。
注意:同一個人可以被查詢多次,但只輸出一次。
輸入樣例1:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
8
55555 44444 10000 88888 22222 11111 23333 88888
輸出樣例1:
10000 88888 23333
輸入樣例2:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
4
55555 44444 22222 11111
輸出樣例2:
No one is handsome
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int a[100000]={0};
int main()
{
int n,k,x,m,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>k;
for(int j=1;j<=k;j++)
{
cin>>x;
if(k!=1) a[x]+=k-1;
}
}
cin>>m ;
for(int i=1;i<=m;i++)
{
cin>>x;
if(a[x]==0)
{
if(sum!=0) cout<<" ";
printf("%05d",x);
a[x]=-1;
sum++;
}
}
if(sum==0) cout<<"No one is handsome" <<endl;
return 0;
}
7-5 重要的話說三遍 (5分)
這道超級簡單的題目沒有任何輸入。
你只需要把這句很重要的話 —— “I'm gonna WIN!”——連續輸出三遍就可以了。
注意每遍佔一行,除了每行的回車不能有任何多餘字元。
I'm gonna WIN!
I'm gonna WIN!
I'm gonna WIN!
7-6 奇偶分家 (10分)
給定N
個正整數,請統計奇數和偶數各有多少個?
輸入格式:
輸入第一行給出一個正整N
(≤1000);第2行給出N
個非負整數,以空格分隔。
輸出格式:
在一行中先後輸出奇數的個數、偶數的個數。中間以1個空格分隔。
輸入樣例:
9
88 74 101 26 15 0 34 22 77
輸出樣例:
3 6
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int main()
{
int n,x,o=0,j=0;
cin>>n;
while(n--)
{
cin>>x;
if(x%2==0) o++;
else j++;
}
cout<<j<<" "<<o;
return 0;
}
7-7 輸出GPLT (20分)
給定一個長度不超過10000的、僅由英文字母構成的字串。請將字元重新調整順序,按GPLTGPLT....
這樣的順序輸出,並忽略其它字元。當然,四種字元(不區分大小寫)的個數不一定是一樣多的,若某種字元已經輸出完,則餘下的字元仍按GPLT
的順序列印,直到所有字元都被輸出。
輸入格式:
輸入在一行中給出一個長度不超過10000的、僅由英文字母構成的非空字串。
輸出格式:
在一行中按題目要求輸出排序後的字串。題目保證輸出非空。
輸入樣例:
pcTclnGloRgLrtLhgljkLhGFauPewSKgt
輸出樣例:
GPLTGPLTGLTGLGLL
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int main()
{
string s;
cin>>s;
int g=0,p=0,l=0,t=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='G'||s[i]=='g')g++;
if(s[i]=='P'||s[i]=='p')p++;
if(s[i]=='L'||s[i]=='l')l++;
if(s[i]=='T'||s[i]=='t')t++;
}
while(g||p||l||t)
{
if(g){cout<<"G";g--;}
if(p){cout<<"P";p--;}
if(l){cout<<"L";l--;}
if(t){cout<<"T";t--;}
}
return 0;
}
7-8 後天 (5分)
如果今天是星期三,後天就是星期五;如果今天是星期六,後天就是星期一。我們用數字1到7對應星期一到星期日。給定某一天,請你輸出那天的“後天”是星期幾。
輸入格式:
輸入第一行給出一個正整數D
(1 ≤ D
≤ 7),代表星期裡的某一天。
輸出格式:
在一行中輸出D
天的後天是星期幾。
輸入樣例:
3
輸出樣例:
5
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
int main()
{
int d;
cin>>d;
if(d+2>7)
cout<<d+2-7;
else cout<<d+2;
return 0;
}
7-9 搶紅包 (25分)
沒有人沒搶過紅包吧…… 這裡給出N個人之間互相發紅包、搶紅包的記錄,請你統計一下他們搶紅包的收穫。
輸入格式:
輸入第一行給出一個正整數N(≤104),即參與發紅包和搶紅包的總人數,則這些人從1到N編號。隨後N行,第i行給出編號為i的人發紅包的記錄,格式如下:
K**N1P1⋯NKP**K
其中K(0≤K≤20)是發出去的紅包個數,N**i是搶到紅包的人的編號,P**i(>0)是其搶到的紅包金額(以分為單位)。注意:對於同一個人發出的紅包,每人最多隻能搶1次,不能重複搶。
輸出格式:
按照收入金額從高到低的遞減順序輸出每個人的編號和收入金額(以元為單位,輸出小數點後2位)。每個人的資訊佔一行,兩數字間有1個空格。如果收入金額有並列,則按搶到紅包的個數遞減輸出;如果還有並列,則按個人編號遞增輸出。
輸入樣例:
10
3 2 22 10 58 8 125
5 1 345 3 211 5 233 7 13 8 101
1 7 8800
2 1 1000 2 1000
2 4 250 10 320
6 5 11 9 22 8 33 7 44 10 55 4 2
1 3 8800
2 1 23 2 123
1 8 250
4 2 121 4 516 7 112 9 10
輸出樣例:
1 11.63
2 3.63
8 3.63
3 2.11
7 1.69
6 -1.67
9 -2.18
10 -3.26
5 -3.26
4 -12.32
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
//int p[10005]={0};
struct node
{
int id,num, v;
}p[10000];
bool cmp(struct node a,struct node b)
{
if(a.v!=b.v) return a.v>b.v;
else if(a.num!=b.num) return a.num>b.num;
else if(a.id!=b.id) return a.id<b.id;
}
int main()
{
int n,k,x,y,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
sum=0;
p[i].id=i;
cin>>k;
for(int j=1;j<=k;j++)
{
cin>>x>>y;
p[x].v+=y;
p[x].num++;
sum=sum+y;
}
p[i].v-=sum;
}
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;i++) printf("%d %.2lf\n",p[i].id,(double)p[i].v/100);
return 0;
}
7-10 排座位 (25分)
佈置宴席最微妙的事情,就是給前來參宴的各位賓客安排座位。無論如何,總不能把兩個死對頭排到同一張宴會桌旁!這個艱鉅任務現在就交給你,對任何一對客人,請編寫程式告訴主人他們是否能被安排同席。
輸入格式:
輸入第一行給出3個正整數:N
(≤100),即前來參宴的賓客總人數,則這些人從1到N
編號;M
為已知兩兩賓客之間的關係數;K
為查詢的條數。隨後M
行,每行給出一對賓客之間的關係,格式為:賓客1 賓客2 關係
,其中關係
為1表示是朋友,-1表示是死對頭。注意兩個人不可能既是朋友又是敵人。最後K
行,每行給出一對需要查詢的賓客編號。
這裡假設朋友的朋友也是朋友。但敵人的敵人並不一定就是朋友,朋友的敵人也不一定是敵人。只有單純直接的敵對關係才是絕對不能同席的。
輸出格式:
對每個查詢輸出一行結果:如果兩位賓客之間是朋友,且沒有敵對關係,則輸出No problem
;如果他們之間並不是朋友,但也不敵對,則輸出OK
;如果他們之間有敵對,然而也有共同的朋友,則輸出OK but...
;如果他們之間只有敵對關係,則輸出No way
。
輸入樣例:
7 8 4
5 6 1
2 7 -1
1 3 1
3 4 1
6 7 -1
1 2 1
1 4 1
2 3 -1
3 4
5 7
2 3
7 2
輸出樣例:
No problem
OK
OK but...
No way
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
//int p[10005]={0};
int a[101][101],b[101];
/*//並查集板子
int find(int x)
{
//while(x!=pre[x]) //如果該結點的父結點不是它自身
//x=pre[x]; //那麼就繼續找它的父結點的父結點
return x==pre[x]?x:find(pre[x]);
}
//查詢函式:用於查詢結點的父結點。
void Union(int x,int y)
{
int fx=find(x); //找到x的根結點
int fy=find(y); //找到y的根結點
if(fx!=fy) //如果x和y的根結點不相同(x和y不屬於同一個聯通分支)
pre[fx]=fy; //就把x的根結點的父結點改為y的根結點
}//合併函式
*/
int find(int x)
{
return b[x]==x?x:b[x]=find(b[x]);
}
int main()
{
int n,m,k,x,y,z,p,q;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)b[i]=i;
for(int i=0;i<m;i++)
{
cin>>x>>y>>z;
if(z==-1) a[x][y]=a[y][x]=1;
else
{
int x1=find(x);//查詢
int y1=find(y);
if(x1!=y1) b[x1]=y1;//合併
}
}
for(int i=0;i<k;i++)
{
cin>>p>>q;
int p1=find(p);
int q1=find(q);
if(q1==p1&&!a[p][q]) printf("No problem\n");
else if(q1==p1&&a[p][q]) printf("OK but...\n");
else if(q1!=p1&&!a[p][q]) printf("OK\n");
else if(q1!=p1&&a[p][q]) printf("No way\n");
}
return 0;
}
7-11 玩轉二叉樹 (25分)
給定一棵二叉樹的中序遍歷和前序遍歷,請你先將樹做個鏡面反轉,再輸出反轉後的層序遍歷的序列。所謂鏡面反轉,是指將所有非葉結點的左右孩子對換。這裡假設鍵值都是互不相等的正整數。
輸入格式:
輸入第一行給出一個正整數N
(≤30),是二叉樹中結點的個數。第二行給出其中序遍歷序列。第三行給出其前序遍歷序列。數字間以空格分隔。
輸出格式:
在一行中輸出該樹反轉後的層序遍歷的序列。數字間以1個空格分隔,行首尾不得有多餘空格。
輸入樣例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
輸出樣例:
4 6 1 7 5 3 2
7-12 關於堆的判斷 (25分)
將一系列給定數字順序插入一個初始為空的小頂堆H[]
。隨後判斷一系列相關命題是否為真。命題分下列幾種:
x is the root
:x
是根結點;x and y are siblings
:x
和y
是兄弟結點;x is the parent of y
:x
是y
的父結點;x is a child of y
:x
是y
的一個子結點。
輸入格式:
每組測試第1行包含2個正整數N
(≤ 1000)和M
(≤ 20),分別是插入元素的個數、以及需要判斷的命題數。下一行給出區間[−10000,10000]內的N
個要被插入一個初始為空的小頂堆的整數。之後M
行,每行給出一個命題。題目保證命題中的結點鍵值都是存在的。
輸出格式:
對輸入的每個命題,如果其為真,則在一行中輸出T
,否則輸出F
。
輸入樣例:
5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10
輸出樣例:
F
T
F
T
7-13 天梯地圖 (30分)
本題要求你實現一個天梯賽專屬線上地圖,隊員輸入自己學校所在地和賽場地點後,該地圖應該推薦兩條路線:一條是最快到達路線;一條是最短距離的路線。題目保證對任意的查詢請求,地圖上都至少存在一條可達路線。
輸入格式:
輸入在第一行給出兩個正整數N
(2 ≤ N
≤ 500)和M
,分別為地圖中所有標記地點的個數和連線地點的道路條數。隨後M
行,每行按如下格式給出一條道路的資訊:
V1 V2 one-way length time
其中V1
和V2
是道路的兩個端點的編號(從0到N
-1);如果該道路是從V1
到V2
的單行線,則one-way
為1,否則為0;length
是道路的長度;time
是通過該路所需要的時間。最後給出一對起點和終點的編號。
輸出格式:
首先按下列格式輸出最快到達的時間T
和用節點編號表示的路線:
Time = T: 起點 => 節點1 => ... => 終點
然後在下一行按下列格式輸出最短距離D
和用節點編號表示的路線:
Distance = D: 起點 => 節點1 => ... => 終點
如果最快到達路線不唯一,則輸出幾條最快路線中最短的那條,題目保證這條路線是唯一的。而如果最短距離的路線不唯一,則輸出途徑節點數最少的那條,題目保證這條路線是唯一的。
如果這兩條路線是完全一樣的,則按下列格式輸出:
Time = T; Distance = D: 起點 => 節點1 => ... => 終點
輸入樣例1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
5 4 0 2 3
5 9 1 1 4
0 6 0 1 1
7 3 1 1 2
8 3 1 1 2
2 5 0 2 2
2 1 1 1 1
1 5 0 1 3
1 4 0 1 1
9 7 1 1 3
3 1 0 2 5
6 3 1 2 1
5 3
輸出樣例1:
Time = 6: 5 => 4 => 8 => 3
Distance = 3: 5 => 1 => 3
輸入樣例2:
7 9
0 4 1 1 1
1 6 1 3 1
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 3 1
3 2 1 2 1
4 5 0 2 2
6 5 1 2 1
3 5
輸出樣例2:
Time = 3; Distance = 4: 3 => 2 => 5
7-14 喊山 (30分)
喊山,是人雙手圍在嘴邊成喇叭狀,對著遠方高山發出“喂—喂喂—喂喂喂……”的呼喚。呼喚聲通過空氣的傳遞,迴盪於深谷之間,傳送到人們耳中,發出約定俗成的“訊號”,達到聲訊傳遞交流的目的。原來它是彝族先民用來求援呼救的“訊號”,慢慢地人們在生活實踐中發現了它的實用價值,便把它作為一種交流工具世代傳襲使用。(圖文摘自:http://news.xrxxw.com/newsshow-8018.html)
一個山頭呼喊的聲音可以被臨近的山頭同時聽到。題目假設每個山頭最多有兩個能聽到它的臨近山頭。給定任意一個發出原始訊號的山頭,本題請你找出這個訊號最遠能傳達到的地方。
輸入格式:
輸入第一行給出3個正整數n
、m
和k
,其中n
(≤10000)是總的山頭數(於是假設每個山頭從1到n
編號)。接下來的m
行,每行給出2個不超過n
的正整數,數字間用空格分開,分別代表可以聽到彼此的兩個山頭的編號。這裡保證每一對山頭只被輸入一次,不會有重複的關係輸入。最後一行給出k
(≤10)個不超過n
的正整數,數字間用空格分開,代表需要查詢的山頭的編號。
輸出格式:
依次對於輸入中的每個被查詢的山頭,在一行中輸出其發出的呼喊能夠連鎖傳達到的最遠的那個山頭。注意:被輸出的首先必須是被查詢的個山頭能連鎖傳到的。若這樣的山頭不只一個,則輸出編號最小的那個。若此山頭的呼喊無法傳到任何其他山頭,則輸出0。
輸入樣例:
7 5 4
1 2
2 3
3 1
4 5
5 6
1 4 5 7
輸出樣例:
2
6
4
0
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
struct node{
int x,num;
}s,s2;
vector<int> v[10005];
int vis[10005],maxx,ans;
void BFS(int t)
{
memset(vis,0,sizeof(vis));
queue<node> q;
s.x=t,s.num=1;
q.push(s);
maxx=-1;vis[t]=1;ans=t;
while(!q.empty())
{
node s1=q.front();q.pop();
if(s1.num>maxx) maxx=s1.num,ans=s1.x;
else if(s1.num==maxx) ans=min(s1.x,ans);
for(int i=0;i<v[s1.x].size();i++)
{
if(!vis[v[s1.x][i]])
{
s2.x=v[s1.x][i],s2.num=s1.num+1;
q.push(s2);
vis[s2.x]=1;
}
}
}
}
int main()
{
int n,m,k,a,b,t;
cin>>n>>m>>k;
for(int i=0;i<m;i++)
{
cin>>a>>b;
v[a].push_back(b);
v[b].push_back(a);
}
for(int i=0;i<k;i++)
{
cin>>t;
BFS(t);
if(ans==t)cout<<"0"<<endl;
else cout<<ans<<endl;
}
return 0;
}
7-15 長城 (30分)
正如我們所知,中國古代長城的建造是為了抵禦外敵入侵。在長城上,建造了許多烽火臺。每個烽火臺都監視著一個特定的地區範圍。一旦某個地區有外敵入侵,值守在對應烽火臺上的士兵就會將敵情通報給周圍的烽火臺,並迅速接力地傳遞到總部。
現在如圖1所示,若水平為南北方向、垂直為海拔高度方向,假設長城就是依次相聯的一系列線段,而且在此範圍內的任一垂直線與這些線段有且僅有唯一的交點。
圖 1
進一步地,假設烽火臺只能建造線上段的端點處。我們認為烽火臺本身是沒有高度的,每個烽火臺只負責向北方(圖1中向左)瞭望,而且一旦有外敵入侵,只要敵人與烽火臺之間未被山體遮擋,哨兵就會立即察覺。當然,按照這一軍規,對於南側的敵情各烽火臺並不負責任。一旦哨兵發現敵情,他就會立即以狼煙或烽火的形式,向其南方的烽火臺傳遞警報,直到位於最南側的總部。
以圖2中的長城為例,負責守衛的四個烽火臺用藍白圓點示意,最南側的總部用紅色圓點示意。如果紅色星形標示的地方出現敵情,將被哨兵們發現並沿紅色折線將警報傳遞到總部。當然,就這個例子而言只需兩個烽火臺的協作,但其他位置的敵情可能需要更多。
然而反過來,即便這裡的4個烽火臺全部參與,依然有不能覆蓋的(黃色)區域。
圖 2
另外,為避免歧義,我們在這裡約定,與某個烽火臺的視線剛好相切的區域都認為可以被該烽火臺所監視。以圖3中的長城為例,若A、B、C、D點均共線,且在D點設定一處烽火臺,則A、B、C以及線段BC上的任何一點都在該烽火臺的監視範圍之內。
圖 3
好了,倘若你是秦始皇的太尉,為不致出現更多孟姜女式的悲劇,如何在保證長城安全的前提下,使消耗的民力(建造的烽火臺)最少呢?
輸入格式:
輸入在第一行給出一個正整數N
(3 ≤ N
≤105),即刻畫長城邊緣的折線頂點(含起點和終點)數。隨後N
行,每行給出一個頂點的x
和y
座標,其間以空格分隔。注意頂點從南到北依次給出,第一個頂點為總部所在位置。座標為區間[−109,109)內的整數,且沒有重合點。
輸出格式:
在一行中輸出所需建造烽火臺(不含總部)的最少數目。
輸入樣例:
10
67 32
48 -49
32 53
22 -44
19 22
11 40
10 -65
-1 -23
-3 31
-7 59
輸出樣例:
2