【NOIP2018複習】B (DP)
B
時間限制:1000MS記憶體限制:256000KB
題目描述
題目背景: ly童鞋上得廳堂下得廚房,左手羽毛右手乒乓,更不用說那精湛的鐵頭功夫了。然而從未接觸過武俠的他並不擅長輕功,於是他決定用梅花樁練習輕功,從此出任CEO贏取白富美修身齊家治國平天下走上人生的巔峰 題目描述: 一共有 n 個木樁,要求從起點(0)開始,經過所有梅花樁,恰好到達終點 n,ly童鞋一共會 k 種門派的輕功,不同門派的輕功經過的梅花樁數不同,花費時間也不同。但是ly一次只能使用一種輕功,當他使用別的門派的輕功時,需要花費 W 秒切換(開始時可以是任意門派,不需要更換時間)。由於ly手(jio)殘,所以經過某些梅花樁(包括起點和終點)時他不能使用一些門派的輕功。ly想知道他最快多久能到達終點,當然瞭如果無解則輸出-1。
輸入
第一行 n,k,W 接下來 k 行,每行為 ai 和 wi 代表第 i 種輕功花費 vi 秒經過 ai 個木樁。 接下來一行 Q 為限制條件數量。 接下來 Q 行,每行為 xi 和 ki 代表第 xi 個梅花樁不能使用第 ki 種門派的輕功經過。
輸出
一行答案即所需最短時間。
輸入樣例複製
Sample Input1/qinggong.in: 6 2 5 1 1 3 10 2 1 1 2 1 Sample Input2/qinggong.out: 6 2 5 1 1 3 10 0
輸出樣例複製
樣例解釋 1: 先用第二種輕功花費 10 秒到 3,再用 5 秒切換到第一種輕功,最後再用 3 秒時間到 6.一共花費 10+5+3=18 秒 Sample Output2: 6 樣例解釋 2: 直接花費 6 秒到 6;
說明
Data Constraint 20%的資料 n<=20,k<=10,Q<=200; 對於另外 20%的資料 W=0 對於另外 20%的資料 Q=0 所以資料滿足 n<=500,k<=100,Q<=50000,vi<=1e7; 保證資料合法 Hint Q:請問第一題可不可以往回跳 A:不可以 題目並不太難,同志仍須硬肝 題解:簡單的DP, f[i,j]表示在第i個點以第j種輕功起跳的最小花費時間 預處理出每種輕功的非法起跳點和落地點
const maxn=500; maxm=500; inf='1030t2.in'; var f:array[0..maxn,0..100]of longint; vv,v:array[0..maxn,0..maxm]of boolean; a:array[0..maxn,1..2]of longint; n,m,i,j,w,k,ans,po:longint; procedure init; var i,q,x,y:longint; begin readln(n,m,w); for i:=1 to m do readln(a[i,1],a[i,2]); readln(q); for i:=1 to q do begin readln(x,y); vv[x,y]:=true; end; for i:=0 to n do for j:=1 to m do for k:=0 to a[j,1] do if i+k<=n then if vv[i+k,j] then v[i,j]:=true; for i:=0 to n do for j:=0 to m do f[i,j]:=maxlongint div 3; for i:=1 to m do f[0,i]:=0; end; function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end; begin // assign(input,inf);reset(input); init; for i:=0 to n do for j:=1 to m do if (v[i,j]=false) then begin po:=i+a[j,1]; if (po>n) then continue; if (vv[po,j]) then continue; if po=n then begin for k:=1 to m do begin // if vv[i+a[j,1],k] then continue; f[po,k]:=min(f[po,k],f[i,j]+a[j,2]); end; continue; end; for k:=1 to m do begin if vv[po,k] then continue; if j<>k then f[po,k]:=min(f[po,k],f[i,j]+a[j,2]+w) else f[po,k]:=min(f[po,k],f[i,j]+a[j,2]); end; end; ans:=maxlongint; for i:=1 to m do begin ans:=min(ans,f[n,i]); end; if ans=maxlongint div 3 then writeln(-1) else writeln(ans); // close(input); end.