POJ2528的另一种解法(线段切割)
題目:Mayor's posters
?
首先本題題意是:有一面墻,被等分為1QW份,一份的寬度為一個(gè)單位寬度。現(xiàn)在往墻上貼N張海報(bào),每張海報(bào)的寬度是任意
的,但是必定是單位寬度的整數(shù)倍,且<=1QW。后貼的海報(bào)若與先貼的海報(bào)有交集,后貼的海報(bào)必定會(huì)全部或局部覆蓋先貼的海
報(bào)。現(xiàn)在給出每張海報(bào)所貼的位置(左端位置和右端位置),問(wèn)張貼完N張海報(bào)后,還能看見多少?gòu)埡?bào)?
?
利用線段切割,由于后貼的海報(bào)可能會(huì)覆蓋前面的,而很明顯知道前面的海報(bào)不會(huì)影響后面海報(bào)的可見性,所以應(yīng)該從后面往
前面推。
?
所以程序中就有:for(i=n-1;i>=0;i--)???
現(xiàn)在我們暫時(shí)只分析前一張海報(bào)與后一張海報(bào)的關(guān)系就可以了,然后遞推就可以了。
我們用海報(bào)的長(zhǎng)度來(lái)表示可見性,如果長(zhǎng)度大于0,當(dāng)然就可見啊
對(duì)于海報(bào)之間的關(guān)系,只有那么幾種情況,但是看程序中只有3種關(guān)系,實(shí)際上在統(tǒng)計(jì)可見性時(shí)我們說(shuō)只需要3種就夠了,為什
么呢?
?
我們可以自己模擬一下:
如果兩張海報(bào)沒(méi)有交集,那么下面的那張海報(bào)一定是可見的,所以長(zhǎng)度當(dāng)然大于0,
如果兩張海報(bào)有交集,就必然有4種關(guān)系,但是這里我們相當(dāng)于只有兩種就夠了,就是后面的覆蓋前面的右半部分,或者后面的
覆蓋前面的左半部分,注意我們開始memset所有的海報(bào)長(zhǎng)度是0,所以如果出現(xiàn)后面的海報(bào)全部覆蓋前面的海報(bào)的情況就不用
管,因?yàn)樗褪?,但是還有一種關(guān)系,就是后面的海報(bào)覆蓋前面海報(bào)的中間部分,這樣的話我們就可以把它當(dāng)成覆蓋左邊部分
或者覆蓋右邊部分,因?yàn)槲覀兊呐袛嗾Z(yǔ)句是
?if(l<node[k].x)?
?if(r>node[k].y)???
很明顯可以看出實(shí)際上這兩個(gè)語(yǔ)句包含了3種情況。而不僅僅代表只覆蓋右部分或者左部分。
這樣我們?cè)诮Y(jié)構(gòu)體里面用ans統(tǒng)計(jì)每張海報(bào)最終的長(zhǎng)度,實(shí)際上不一定是真正的長(zhǎng)度哈,比如后一張只覆蓋前一張的和中間部分
的那一種情況,實(shí)際上ans就只記錄了前面的海報(bào)的左邊部分,所以這樣本題就解決了,線段切割實(shí)現(xiàn)起來(lái)更容易。
注意線段切割與矩形切割適用的范圍:對(duì)邊界范圍大,操作數(shù)少的題目,我們選擇矩形切割或者線段切割。?
#include <stdio.h> #include <string.h>const int N = 10005;typedef struct {int x,y;int ans; }Node;Node node[N];int n;void Cover(int l,int r,int k,int c) {while(k<n&&(r<node[k].x||l>node[k].y)) k++;if(k>=n) //當(dāng)前進(jìn)行切割的線段并沒(méi)有和后面的線段相交{node[c].ans+=r-l+1;return;}if(l<node[k].x) Cover(l,node[k].x-1,k+1,c); //當(dāng)前線段的右邊被覆蓋;if(r>node[k].y) Cover(node[k].y+1,r,k+1,c); //當(dāng)前線段的左邊被覆蓋; }int main() {int t,i,sum;scanf("%d",&t);while(t--){sum=0;memset(node,0,sizeof(node));scanf("%d",&n);for(i=0;i<n;i++)scanf("%d%d",&node[i].x,&node[i].y);for(i=n-1;i>=0;i--) //這里是用后面的海報(bào)覆蓋前面的海報(bào),所以要從后面開始進(jìn)行插入(進(jìn)行線段切割);Cover(node[i].x,node[i].y,i+1,i);for(i=0;i<n;i++)if(node[i].ans>0)sum++;printf("%d\n",sum);}return 0; }
?
?
總結(jié)
以上是生活随笔為你收集整理的POJ2528的另一种解法(线段切割)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 经典的括号匹配问题
- 下一篇: POJ1151(矩形切割入门题)