1. 程式人生 > >【NOIP2018複習】B (DP)

【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.