任意多邊形周長的求取

問題提出:

在一個矩形方格中,隨機地塗表格,求所塗多邊形的周長。


        我們如果去求圖中所有黑點所組成的多邊形的周長呢?小學我們就學過切割法。對於凸邊形來說,其周長可以等價於一個大矩形的周長。如下圖所示

====》

即周長爲4*5=20

        但對於凹多邊形來說,這就不對了,對於這個凹字就可以看出2*(4+5)!=18。那麼應該怎麼求呢?對於普通程序員來說,最熟悉的是遍歷了,但我可以說的是,有更簡單的方法。

        我們來分析下,每個小方塊矩形有4條邊,但相鄰的方塊會有重複的邊。如果我們把重複的邊減掉,不就可以得到其周長了嗎。先舉個例子。對於兩個小方塊來說,重合的邊爲2,故其周長爲2*4-2=2*(1+2)=6。其實認真想想也很容易想明白的。好了,那我們怎麼求重合的邊數呢?如果我們把每個小方塊黑點當成一個個的點,然後相鄰的黑點連成線,那就是我們所說的圖了。所重合的邊數,就是這個圖邊數的兩倍,即2e(e爲此圖邊的個數)


        根據圖論的知識,所有點的度之和爲邊數的2倍,。設黑點數爲n,則周長爲。我們來上圖中的周長:4*12-(1+3+2+3+4+3+2+2+4+3+2+1)=48-30=18。

        以上方法所計算的結果是包含內點的,如第一幅圖中右下角有一個內點,即白點周邊全是黑的。如果不想包括內點,那麼可以先進行對內點處理,全變成黑點,然後再處理。對於第一幅圖,如果計算內點的話,即:4*25-(1+2+3+2+2+1+3+2+2+1+1+1+3+3+1+2+3+2+2+3+2+1+1+2+2)=100-48=52。而根據切割法原理,我們可以得到周長爲2*(2+4)+2(3+4)-2+2(3+4)+2(4+2)+2=12+14+14+12=52。

代碼爲:

int perimeter(int **d,int n)
{
//	Print(d,n);
	int director[4][2]={{1,0},{0,-1},{-1,0},{0,1}};//方位,右-上-左-下
	///////////////////////預處理/////////////////////////////////
	//將內點賦1
	bool isOne=true;
	for(int i=1;i<n-1;i++){
		for(int j=1;j<n-1;j++){
			if(d[i][j]==0){
				isOne=true;
				for(int k=0;k<4;k++){
					if(d[i+director[k][0]][j+director[k][1]]!=1){//如果有一個方位不爲1,則此點不符合條件
						isOne=false;
						break;
					}
				}
				if(isOne)
					d[i][j]=1;
			}
		}
	}
	int Onecount=0,
		degree=0;
	for(int i=1;i<n-1;i++){
		for(int j=1;j<n-1;j++){
			if(d[i][j]==1){
				Onecount++;//記錄值爲1的點數
				for(int k=0;k<4;k++){
					if(d[i+director[k][0]][j+director[k][1]]==1)//記錄四個方位值爲1的點數
						degree++;
				}
			}
		}
	}
	return 4*Onecount-degree;//返回周長
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章