2011年10月7日 星期五

Sunny Mountains

內容:
Smith 夫婦到喜馬拉雅山去度蜜月。當太陽下山時,山頭的白雪被夕陽染成了紅色,這樣的景觀讓他們驚豔。
一般的人都會被這樣的景象所感動,但是 Smith 先生無法克服對數字的沈迷,他開始量測距離。這讓 Smith 太太很不開心。

問題

你需要幫 Smith 先生計算被夕陽染紅的山坡一共有幾公尺。他的蜜月就靠你了,你動作要快。
為了簡化問題,假設太陽下山時陽光 (Sunbeams)是水平的,地形則是以山巔及山坳的座標表示。如下圖 所示,地形是一連串的山巔及山坳,山巔及山坳會交錯出現。

圖中的向陽山坡 (Sunny mountain sides) 以粗線表示,地形的座標則以粗點表示。
這個問題便是要計算粗線的總長度。
請注意:(1) 對所有的座標 (x, y), 0 <= x <= 30000 and 0 <= y <= 8848;(2) 單位為公尺;(3) 所有的 X 座標卻互不相同;(4) 最左邊的點的 X 座標為 0,最右邊的點的 Y 座標為 0;(5) 座標總數 n <= 100。



輸入說明:


輸入的第一行為 C (0 < C < 100 ),表示有幾筆測資。
每筆測資的第一行為座標數 N,接下來的 N 行為定義地形的座標,每行有兩個以空白隔開的整數 xy。第一個數字 x 為 X 座標,第二個數字 y 為 Y 座標。


輸出說明:

每筆測資請輸出一行,每行有一個含有兩位小數的實數。這個實數表該筆測資的向陽山坡的總長度。


範例輸入:
若題目沒有特別說明,則應該以多測資的方式讀取,若不知如何讀取請參考 a001 的範例程式。

2
11
1100 1200
0 500
1400 100
600 600
2800 0
400 1100
1700 600
1500 800
2100 300
1800 700
2400 500
2
0 1000
1000 0

範例輸出

1446.34
1414.21


出處:UVa ACM 920

2 則留言:

  1. 用了
    兩點式公式
    兩點距離公式
    數學第6章部分

    圖形部分可複製到EXCEL
    然後按X軸排序(遞增)
    再把資料變成圖表(XY散布圖-帶折線沒有資料標記)

    Dim X() As Long
    Dim Y() As Long
    Dim ans As Single
    Dim tall As Long

    Private Sub Form_Load()
    Me.Hide
    Open App.Path & "\in.txt" For Input As #1
    Open App.Path & "\out.txt" For Output As #2
    Input #1, C

    For tt = 1 To C

    ans = 0: tall = 0
    Input #1, N
    ReDim X(N)
    ReDim Y(N)

    For i = 1 To N
    Line Input #1, XY
    XXYY = Split(XY)
    X(i) = Val(XXYY(0))
    Y(i) = Val(XXYY(1))
    Next i

    Call sort

    For i = N To 1 Step -1
    If Y(i - 1) > tall Then
    ans = ans + Line_long(X(i - 1), Y(i - 1), The_X(X(i - 1), Y(i - 1), X(i), Y(i), tall), tall)
    tall = Y(i - 1)
    End If
    Next i

    Print #2, Format(ans, "0.00")
    Next tt

    Close #2
    Close #1
    End
    End Sub

    Function Line_long(xx1, yy1, xx2, yy2) '求線段長度
    Line_long = ((xx1 - xx2) ^ 2 + (yy1 - yy2) ^ 2) ^ 0.5
    End Function

    Function The_X(xx1, yy1, xx2, yy2, yy) '兩點式求X
    The_X = (yy - yy1) * ((xx2 - xx1) / (yy2 - yy1)) + xx1
    End Function

    Sub sort() '排序
    For i = 1 To UBound(X) - 1
    For j = i + 1 To UBound(X)
    If X(i) > X(j) Then
    Call change(X(i), X(j))
    Call change(Y(i), Y(j))
    End If
    Next j
    Next i
    End Sub

    Sub change(A, B)
    T = A
    A = B
    B = T
    End Sub



    in.txt-----------
    2
    11
    1100 1200
    0 500
    1400 100
    600 600
    2800 0
    400 1100
    1700 600
    1500 800
    2100 300
    1800 700
    2400 500
    2
    0 1000
    1000 0

    out.txt---------------
    1446.34
    1414.21

    回覆刪除
  2. Dim Ans, High, X, Y, Z

    Private Sub Form_Load()
    Me.Hide
    Open App.Path & "\in.txt" For Input As #1
    Open App.Path & "\out.txt" For Output As #2
    Input #1, Ti

    For m = 1 To Ti

    Input #1, n
    ReDim X(n), Y(n), Z(n)
    For MM = 1 To n
    Input #1, XX, YY
    X(MM) = XX
    Y(MM) = YY
    Next
    Ans = 0
    Call A1
    Call A2

    Print #2, Format(Ans, "#.##")

    Next

    Close
    Close


    End
    End Sub


    Sub A1()

    For i = 1 To UBound(X)
    For j = 1 To UBound(X) - 1
    If X(j) < X(j + 1) Then
    tmp = X(j)
    tmp2 = Y(j)
    X(j) = X(j + 1)
    Y(j) = Y(j + 1)
    X(j + 1) = tmp
    Y(j + 1) = tmp2
    End If
    Next
    Next

    End Sub


    Sub A2()

    Dim X1, Y1, X2, Y2, H

    For i = 2 To UBound(X)
    Z(i) = Cnt2(X(i - 1), Y(i - 1), X(i), Y(i))
    Next


    H = Y(2)



    For i = 2 To UBound(X)
    X1 = X(i - 1)
    X2 = X(i)
    Y1 = Y(i - 1)
    Y2 = Y(i)



    If Z(i) < 0 Then

    If Y2 = H Then Ans = Ans + Cnt(X1, Y1, X2, Y2)


    If Y2 > H Then
    X1 = (X1 * Z(i) + H - Y1) / Z(i)
    Y1 = H
    Ans = Ans + Cnt(X1, Y1, X2, Y2)
    H = Y2
    End If

    End If

    Next

    End Sub



    Function Cnt(A, B, C, D)
    Cnt = ((A - C) ^ 2 + (B - D) ^ 2) ^ 0.5
    Print Cnt
    End Function

    Function Cnt2(A, B, C, D)

    Cnt2 = ((B - D) / (A - C))

    End Function

    回覆刪除