演算法競賽入門經典UVa1606 兩親性分子

2021-09-05 10:14:25 字數 2916 閱讀 7028

題目

題目大意:

平面上有n(n

≤1000

n \le 1000

n≤1000

)個點,每個點為白點或者黑點。現在需要放置一條隔板,使得隔板一側的白點數加上另一側的黑點數總數最大。隔板上的點可以看作是任意一側。

這個題的思路是先列舉基準點a,再以基準點a為原點,算出其他點相對基準點的位置,以基準點為原點建立座標;列舉其它點中的乙個b,讓基準點a和點b連成一條線作為本題的隔板,統計隔板兩邊黑點和白點的個數,更新答案。

解題方法:

白點黑點的處理:

把黑點旋轉180°,然後統計時只統計隔板一側的點數

判斷點在隔板的一側:首先把所有其他點按照極角增序排序,利用叉積來判斷兩個點之間的夾角,如果大於0那麼在隔板左側,等於0和隔板共線

極角:利用atctan函式

c++中有兩個計算極角的函式:atan(反正切函式)和atan2(四象限反正切函式)

atan的取值範圍為(−π

2,π2

)(-\frac,\frac)

(−2π​,

2π​)

atan2的取值範圍為(−π

)(-,)

(−π,π)

atan2函式可以區分點所在的象限,更加準確

叉積:u⃗×

v⃗=(

u1v2

−u2v

1)n⃗

=(∣u

⃗∣∣v

⃗∣si

nθ)n

⃗\vec u \times \vec v=(u_1v_2-u_2v_1) \vec n = ( \vert \vec u \vert \vert \vec v \vert sin \theta ) \vec n

u×v=(u

1​v2

​−u2

​v1​

)n=(

∣u∣∣

v∣si

nθ)n(1

)當u1

v2−u

2v

1>0,

sinθ

>0,

θ∈(0

,π),

v⃗相對

n⃗逆時

針旋轉π

以內

(1)當u_1v_2-u_2v_1 > 0,sin\theta >0 ,\theta \in (0,\pi) , \vec v相對 \vec n逆時針旋轉 \pi以內

(1)當u1

​v2​

−u2​

v1​>0,

sinθ

>0,

θ∈(0

,π),

v相對n

逆時針旋

轉π以內(2

)當u1

v2−u

2v

1<0,

sinθ

<0,

θ∈(π

,2π)

,v⃗相

對n⃗逆

時針旋轉

π以

上(2)當u_1v_2-u_2v_1 < 0,sin\theta <0 ,\theta \in (\pi,2\pi) , \vec v相對 \vec n逆時針旋轉 \pi以上

(2)當u1

​v2​

−u2​

v1​<0,

sinθ

<0,

θ∈(π

,2π)

,v相對

n逆時針

旋轉π以

上 ( 3)

u1v2

−u2v

1=0,

sinθ

=0,v

⃗與n⃗

共線

(3)u_1v_2-u_2v_1 = 0,sin\theta = 0 , \vec v 與 \vec n共線

(3)u1​

v2​−

u2​v

1​=0

,sin

θ=0,

v與n共

線 掃瞄時計算l和r的叉積如果≥

0\ge0

≥0,那麼新點r在隔板l的左側,符合要求

#include

#include

#include

#define rep(i,a,b) for(int i=(a); i<(int)(b);++i)

const

int maxn=

1005

;int n,color[maxn]

;struct node

}op[maxn]

,p[maxn]

;bool left

(node& a,node& b)

//叉積

intinfer()

p[k]

.rad=

atan2

(p[k]

.y,p[k]

.x);

++k;

} std:

:sort

(p,p+k)

;int l=

0,r=

0,cnt=2;

//開始有兩個點,乙個是i,也就是算完相對位置後的原點,乙個是l

while

(l//把隔板l轉圈,一直轉完所有的點

while

(r!=l&&

left

(p[l]

,p[r]))

//r是l左邊的點,右手定則

--cnt;

//捨去多計入的點,也可以理解為由於分隔線的旋轉,原來在分隔線上的點現在變為了右側的點,要減掉乙個

++l;

ans=std:

:max

(ans,cnt);}

}return ans;

}int

main()

return0;

}

參考:

atan2與極座標 叉積

uva 1606 思維 極座標掃瞄線)

題意 平面上給出n個點,分為黑白兩種顏色,問在其中給出乙個隔板,使隔板左邊 隔板右邊的棋子數量最大 左右隔板棋子顏色不同 隔板上的棋子算任意一邊 寒假的第一題,屯了很久沒做,自己的思維還是不夠做這個題。列舉每乙個點,當做基準點,算出相對座標,再算出乙個極座標角,用來排序,基準點即可看作是 0,0 再...

演算法競賽入門經典UVa 340

首先,要開闢兩個陣列用於儲存答案序列和猜測序列,正常的猜測序列不會有0,所以只需判斷第乙個數是否為0即可。對於輸出的a來說可以直接遍歷答案序列和猜測序列對應元素是否一樣來求得a。為了求b,對於每個數字 1 9 統計二者出現的次數c1,c2,則min c1,c2 就是該數字對b的貢獻。最後減去a的部分...

例題8 6 兩性親分子 UVa 1606

分析 每次列舉乙個點作為基準點,然後求其他點與這個基準點的夾角,再排一遍序,按照角度從小到大排序,接下來以基準點和其中乙個點的連線開始逆時針掃瞄一遍,直到基準點和另乙個點的連線和開始的那條線之間的角度大於等於180停止,這樣就可以了,我也看了好一會兒題解才看懂,具體看 include include...