【dp】P1064 金明的預算方案

題目描述

金明今天很開心,家裏購置的新房就要領鑰匙了,新房裏有一間金明本身專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說:「你的房間須要購買哪些物品,怎麼佈置,你說了算,只要不超過NN元錢就行」。今天一早,金明就開始作預算了,他把想買的物品分爲兩類:主件與附件,附件是從屬於某個主件的,下表就是一些主件與附件的例子:html

主件 附件node

電腦 打印機,掃描儀ios

書櫃 圖書spa

書桌 檯燈,文具設計

工做椅 無code

若是要買歸類爲附件的物品,必須先買該附件所屬的主件。每一個主件能夠有00個、11個或22個附件。附件再也不有從屬於本身的附件。金明想買的東西不少,確定會超過媽媽限定的NN元。因而,他把每件物品規定了一個重要度,分爲55等:用整數1-515表示,第55等最重要。他還從因特網上查到了每件物品的價格(都是1010元的整數倍)。他但願在不超過NN元(能夠等於NN元)的前提下,使每件物品的價格與重要度的乘積的總和最大。htm

設第jj件物品的價格爲v_[j]v[j],重要度爲w_[j]w[j],共選中了kk件物品,編號依次爲j_1,j_2,…,j_kj1,j2,,jk,則所求的總和爲:blog

v_[j_1] \times w_[j_1]+v_[j_2] \times w_[j_2]+ …+v_[j_k] \times w_[j_k]v[j1]×w[j1]+v[j2]×w[j2]++v[jk]×w[jk]。get

請你幫助金明設計一個知足要求的購物單。string

輸入輸出格式

輸入格式:

 

11行,爲兩個正整數,用一個空格隔開:

N mNm (其中N(<32000)表示總錢數,m(<60)爲但願購買物品的個數。) 從第22行到第m+1m+1行,第jj行給出了編號爲j-1j1的物品的基本數據,每行有3個非負整數

v p qvpq (其中vv表示該物品的價格(v<10000),p表示該物品的重要度(1-5),qq表示該物品是主件仍是附件。若是q=0,表示該物品爲主件,若是q>0,表示該物品爲附件,qq是所屬主件的編號)

 

輸出格式:

 

一個正整數,爲不超過總錢數的物品的價格與重要度乘積的總和的最大值(<200000)。

 

輸入輸出樣例

輸入樣例#1: 
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
輸出樣例#1: 
2200

說明

NOIP 2006 提升組 第二題

 

【思路】:

金明可選的方案:

只選該主件。

選主件和附件1。
選主件和附件2。
全選

f[j]=max(f[j],f[j-a[i][0].v]+a[i][0].w); f[j]=max(f[j],f[j-a[i][0].v-a[i][1].v]+a[i][0].w+a[i][1].w); f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v]+a[i][0].w+a[i][2].w); f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v-a[i][1].v]+a[i][0].w+a[i][2].w+a[i][1].w);
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
const int maxn=999999999;
const int minn=-999999999;
inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int n,m;
struct node {
    int v,w;
} a[67][3];
int vis[67],f[320004]; //vis[]判斷是該主件的第幾個附件
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++) {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(z==0) {
            a[i][0].v=x;
            a[i][0].w=x*y;
        } else {
            if(!vis[z]) {
                a[z][1].v=x;
                a[z][1].w=x*y;
                vis[z]=1;
            } else {
                a[z][2].v=x;
                a[z][2].w=x*y;
            }
        }
    }
    for(int i=1; i<=m; i++) { //m是件數,枚舉從1件到m件這幾種狀況
        for(int j=n; j>=0; j--) { //枚舉空間大小
            /*只選主件*/
            if(j>=a[i][0].v) {
                f[j]=max(f[j],f[j-a[i][0].v]+a[i][0].w);
            }
            /*選主件和附件一*/
            if(j>=a[i][0].v+a[i][1].v) {
                f[j]=max(f[j],f[j-a[i][0].v-a[i][1].v]+a[i][0].w+a[i][1].w);
            }
            /*選主件和附件二*/
            if(j>=a[i][0].v+a[i][2].v) {
                f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v]+a[i][0].w+a[i][2].w);
            }
            /*全選*/
            if(j>=a[i][0].v+a[i][1].v+a[i][2].v) {
                f[j]=max(f[j],f[j-a[i][0].v-a[i][2].v-a[i][1].v]+a[i][0].w+a[i][2].w+a[i][1].w);
            }
        }
    }
    printf("%d",f[n]);
    return 0;
}
相關文章
相關標籤/搜索