【題解】LuoGu1941/noip2014:飛揚的小鳥
阿新 • • 發佈:2018-12-13
這道題是一道比較明顯的dp 表示橫座標為i、高度為j的最少點選數
發現,同一時刻可以點選多次螢幕、不點選則下降 可以理解為:向上做完全揹包,向下做01揹包
邊界也很好處理,若點選一次上升高度為X 則向上飛的話最多飛到m+X,把高出m的都算作m的 另外,障礙物所在處是無法通過的,需要賦一個很大的值
最終的輸出分兩種情況,很好處理,不講了
Code:
uses math; var dp:array[0..11000,0..2000] of longint; l,h,x,y,cnt:array[0..100000] of longint; flag:boolean; n,m,k,i,j,p:longint; ans:int64; begin readln(n,m,k); for i := 1 to n do begin readln(x[i],y[i]); h[i] := m + 1; end; for i := 1 to k do begin read(p); cnt[p] := 1;//打標記 readln(l[p], h[p]); end; for i := 1 to n do for j := 1 to n + m do dp[i][j] := maxlongint >> 1; for i := 1 to m do dp[0][i] := 0;//初始化 for i := 1 to n do begin for j := x[i] + 1 to m + x[i] do //完全揹包 dp[i][j] := min(dp[i - 1][j - x[i]] + 1, dp[i][j - x[i]] + 1); for j := m + 1 to m + x[i] do dp[i][m] := min(dp[i][m], dp[i][j]); for j := 1 to m - y[i] do //01揹包 dp[i][j] := min(dp[i - 1][j + y[i]], dp[i][j]); for j := 1 to l[i] do dp[i][j] := maxlongint >> 1; for j := h[i] to m do dp[i][j] := maxlongint >> 1; end; ans := maxlongint; for i := 1 to m do ans := min(ans, dp[n][i]); if ans < (maxlongint >> 1) then begin writeln(1); writeln(ans); end else begin writeln(0); for i := n downto 1 do begin flag := false; for j := 1 to m do if dp[i][j] < (maxlongint >> 1) then begin flag := true; break; end; if flag then begin ans := 0; for j := 1 to i do inc(ans, cnt[j]); writeln(ans); break; end; end; end; end.