1. 程式人生 > >2006年分割槽聯賽普級組之二 開心的…

2006年分割槽聯賽普級組之二 開心的…

Description

  金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:“你的房間需要購買哪些物品,怎麼佈置,你說了算,只要不超過N 元錢就行”。今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的N 元。於是,他把每件物品規定了一個重要度,分為5 等:用整數1~5 表示,第5 等最重要。他還從因特網上查到了每件物品的價格(都是整數元)。他希望在不超過N 元(可以等於N 元)的前提下,使每件物品的價格與重要度的乘積的總和最大。設第j 件物品的價格為v[j],重要度為w[j],共選中了k 件物品,編號依次為,j1,j2,……jk ,則所求的總和為:v[j1]*w[j1]+v[j2]*w[j2]+……+v[jk]*w[jk] (其中*為乘號) 
  請你幫助金明設計一個滿足要求的購物單。 

Input

輸入的第1 行,為兩個正整數,用一個空格隔開: 
N m (其中N(<30000)表示總錢數,m(<25)為希望購買物品的個數。) 
從第2 行到第m+1 行,第j 行給出了編號為j-1的物品的基本資料,每行有2 個非負整數 
v p (其中v 表示該物品的價格(v≤10000),p 表示該物品的重要度(1~5)) 

Output

輸出只有一個正整數,為不超過總錢數的物品的價格與重要度乘積的總和的最大值(<100000000) 

Sample Input

Sample Output


f[i,j]表示前i件物品在j元限制下的最大重要度,狀態轉移方程為:
f[i,j]=max{f[i-1,j],f[i-1,j-w[i]],v[i]}

(1<=i<=n,1<=j<=m)
f[n,m]即為所求。 時間複雜度:O(nm)
程式1:
var
  n,m,i,j:longint;
  f:array[0..25,0..30000]of longint;
  w,v:array[0..25]of longint;
function max(a,b:longint):longint;
  begin
    if a>b then exit(a) else exit(b);
end;
begin
  readln(m,n);
  for i:=1 to n do
    begin
      readln(w[i],v[i]);
      v[i]:=w[i]*v[i];
    end;
  for i:=1 to n do
    for j:=1 to m do
      begin
        f[i,j]:=f[i-1,j];
        if j>=w[i] then f[i,j]:=max(f[i-1,j],f[i-1,j-w[i]]+v[i]);
      end;
  writeln(f[n,m]);
end.
解題思路2:f[j]表示上篇解題報告的f[i,j],狀態轉移方程為:


f[j]=max{f[j],f[j-w[i]],v[i]}
(1<=i<=n,m>=j>=0)
f[m]為所求。 時間複雜度:O(nm)
程式2:
var
  f,w,v:array[0..30000]of longint;
  n,m,i,j:longint;
function max(x,y:longint):longint;
  begin
    if x>y then exit(x) else exit(y);
end;
begin
  readln(m,n);
  for i:=1 to n do
    begin
      readln(w[i],v[i]);
      v[i]:=v[i]*w[i];
    end;
  for i:=1 to n do
    for j:=m downto 0 do
      if j>=w[i] then f[j]:=max(f[j],f[j-w[i]]+v[i]);
  writeln(f[m]);
end.
版權屬於: Chris
轉載時必須以連結形式註明原始出處及本宣告。