n個不同的顏色的不透明的長方形(1 <= n <= 1000)被放置在一張寬為a長為b的白紙上。
這些長方形被放置時,保證了它們的邊於白紙的邊緣平行。
所有的長方形都放置在白紙內,所以我們會看到不同形狀的各種顏色。
座標系統的原點(0,0)設在這張白紙的左下角,而座標軸則平行於邊緣。
program name: rect1
input format
每行輸入的是放置長方形的方法。
第一行輸入的是那個放在底的長方形(即白紙)。
第 1 行: a , b 和 n, 由空格分開 (1 <=a, b<=10,000)
第 2 到n+1行: 為五個整數 llx, lly, urx, ury, color 這是乙個長方形的左下角座標,右上角座標和顏色。
顏色 1和底部白紙的顏色相同。
sample input (file rect1.in)
20 20 3
2 2 18 18 2
0 8 19 19 3
8 0 10 19 4
output format
輸出檔案應該包含乙個所有能被看到顏色連同該顏色的總面積的清單( 即使顏色的區域不是連續的),按color的增序順序。
不要顯示沒有區域的顏色。
sample output (file rect1.out)
1 91
2 84
3 187
4 38
考慮兩個矩形a,b,其中a覆蓋在b上,則b可以被看到的部分為b-a∩b。
若a沒有與b相交,則必然出現了以下4種情況之一:(由於矩形的頂點沒有包含在矩形內,所以若座標相等也算無交集)
1. a.x1>=b.x2 (a在b右方)
2. a.x2<=b.x1 (a在b左方)
3. a.y1>=b.y2 (a在b上方)
4. a.y2<=b.y1 (a在b下方)
若a與b相交,同樣也會出現4種情況(花括號內的可省略,因為假設a與b相交):
1. b.x12. b.x2>a.x2
3. b.y14. b.y2>a.y2
接下來就輪到矩形切割了:
以下圖為例:
當矩形a覆蓋在矩形b上時,所能看到的部分為s1+s2+s3+s4,我們的目標就是求出s1+s2+s3+s4。
對於相交的4種情況分別進行討論: (每個矩形用左下頂點和右上頂點座標確定)
1. 當且僅當b.x12. 當且僅當b.x13. 當且僅當b.y14. 當且僅當b.y1至此,本題的演算法便不難得到了。
資料結構:
view plain
copy to clipboard
print?
type
rectangle=x1,y1,x2,y2,color:longint;
維護乙個表list存放已經加入了的矩形:
view plain
copy to clipboard
print?
var
list:array[1..max_n] of rectangle
我們還需要兩個過程,加入和刪除矩形:
view plain
copy to clipboard
print?
procedure add(rec:rectangle);
begin
inc(count);
list[count]:=rec;
end;
view plain
copy to clipboard
print?
procedure del(index:longint);
begin
list[index]:=list[count];
dec(count);
end;
當我們每加入乙個矩形(1 to n),都得掃瞄表中所有資料,若有矩形與新矩形相交,則進行矩形切割,即加入上圖中的s1,s2,s3,s4,刪除矩形b,最後掃瞄一遍list,即可統計各種顏色的面積。
還有一種更強的演算法,來自christoph roick or maigo,甚至可以用遞迴直接統計,完全代替list。暫且稱為漂浮法。
主要思想如下:
以逆序來進行放置,即n to 1。逆序的好處在於放置乙個矩形後,俯視看到的就是最終俯視該矩形應該看到的。因為擋著它的矩形在之前已經放置好了,所以可直接統計,為遞迴創造了條件。每放乙個矩形,可以想象成將其扔入一密度很大的海水底部,海分成了n層,然後矩形開始向上浮。在上浮過程中若碰撞到其他的矩形則斷裂成幾個小矩形,繼續上浮,直到浮出水面。於是想到用個遞迴來模擬上浮過程。
maigo的**如下(僅僅40多行!):
program rect1;
const
maxn=1000;
maxcolor=2500;
var fin,fout:text;
x1,y1,x2,y2,color:array[0..maxn]of word;
area:array[1..maxcolor]of longint;
n,i,now:longint;
procedure cal(l,r,b,t,z:longint);
begin
while (z<=n) and ((r<=x1[z]) or (l>=x2[z]) or (t<=y1[z]) or (b>=y2[z])) do inc(z);
if z>n then begin inc(area[now],(r-l)*(t-b));exit;end;
if lx2[z] then begin cal(x2[z],r,b,t,z+1);r:=x2[z];end;
if by2[z] then cal(l,r,y2[z],t,z+1);
end;
begin
assign(fin,'rect1.in');
reset(fin);
read(fin,x2[0],y2[0],n);
x1[0]:=0;y1[0]:=0;color[0]:=1;
for i:=1 to n do
read(fin,x1[i],y1[i],x2[i],y2[i],color[i]);
close(fin);
for i:=n downto 0 do begin
now:=color[i];
cal(x1[i],x2[i],y1[i],y2[i],i+1);
end;
assign(fout,'rect1.out');
rewrite(fout);
for i:=1 to maxcolor do
if area[i]>0 then writeln(fout,i,' ',area[i]);
close(fout);
end.
Shaping Regions 附錯誤解法
include include using namespace std int color 810 810 int values 1005 int main for i 1 i n 1 i for i 1 i n 1 i for i 1 i n 1 i if flag n nmax int squa...
閉式解 解析解
閉式解也被稱為解析解,是通過嚴格的公式所求得的解,即包含分式 三角函式 指數 對數甚至無限級數等基本函式的解的形式。通過給出解的具體函式形式,從解的表示式中就可以算出任何對應值。解析解,又稱為閉式解,是可以用解析表示式來表達的解。在數學上,如果乙個方程或者方程組存在的某些解,是由有限次常見運算的組合...
ambiguous column name解決辦法
在sql語句中,如果使用聯合檢索的話,很有可能會出現ambiguous column name的錯誤。原來在兩張表裡都有的欄位名稱,在選擇語句中要標明是哪張表裡的字段。所以改一下就行了,在報錯的欄位名前面加上該字段的表名 cursor datatool.dbhelpertools.select se...