牛客网-华为机试练习题 16 购物单
描述
王強(qiáng)今天很開心,公司發(fā)給N元的年終獎(jiǎng)。王強(qiáng)決定把年終獎(jiǎng)用于購物,他把想買的物品分為兩類:主件與附件,附件是從屬于某個(gè)主件的,下表就是一些主件與附件的例子:
| 主件 | 附件 |
| 電腦 | 打印機(jī),掃描儀 |
| 書柜 | 圖書 |
| 書桌 | 臺(tái)燈,文具 |
| 工作椅 | 無 |
如果要買歸類為附件的物品,必須先買該附件所屬的主件。每個(gè)主件可以有?0?個(gè)、?1?個(gè)或?2?個(gè)附件。附件不再有從屬于自己的附件。王強(qiáng)想買的東西很多,為了不超出預(yù)算,他把每件物品規(guī)定了一個(gè)重要度,分為?5?等:用整數(shù)?1?~?5?表示,第?5?等最重要。他還從因特網(wǎng)上查到了每件物品的價(jià)格(都是?10?元的整數(shù)倍)。他希望在不超過?N?元(可以等于?N?元)的前提下,使每件物品的價(jià)格與重要度的乘積的總和最大。
????設(shè)第?j?件物品的價(jià)格為?v[j]?,重要度為?w[j]?,共選中了?k?件物品,編號(hào)依次為?j?1?,?j?2?,……,?j?k?,則所求的總和為:
v[j?1?]*w[j?1?]+v[j?2?]*w[j?2?]+?…?+v[j?k?]*w[j?k?]?。(其中?*?為乘號(hào))
????請(qǐng)你幫助王強(qiáng)設(shè)計(jì)一個(gè)滿足要求的購物單。
輸入描述:
輸入的第?1?行,為兩個(gè)正整數(shù),用一個(gè)空格隔開:N?m
(其中?N?(?<32000?)表示總錢數(shù),?m?(?<60?)為希望購買物品的個(gè)數(shù)。)
從第?2?行到第?m+1?行,第?j?行給出了編號(hào)為?j-1?的物品的基本數(shù)據(jù),每行有?3?個(gè)非負(fù)整數(shù)?v?p?q
(其中?v?表示該物品的價(jià)格(?v<10000?),?p?表示該物品的重要度(?1?~?5?),?q?表示該物品是主件還是附件。如果?q=0?,表示該物品為主件,如果?q>0?,表示該物品為附件,?q?是所屬主件的編號(hào))
輸出描述:
?輸出文件只有一個(gè)正整數(shù),為不超過總錢數(shù)的物品的價(jià)格與重要度乘積的總和的最大值(?<200000?)
示例1
輸入:
1000 5 800 2 0 400 5 1 300 5 1 400 3 0 500 2 0輸出:
2200思路:總體還是采用動(dòng)態(tài)規(guī)劃的思想,不過這題有一個(gè)部分物品是附件,買附件必須買主件的約束條件,這樣我們可以只算買主件的動(dòng)態(tài)規(guī)劃,把附件掛到主件下面,這樣買主件從原來的買,不買2種情況變成買0附件,買1附件A,買1附件B,買2附件,不買5種情況,我們計(jì)算的時(shí)候計(jì)算5種情況然后然后然后按動(dòng)態(tài)規(guī)劃的思想往下拆分就可以了
這里因?yàn)楦嬖V我們每個(gè)商品的價(jià)格都是10的整數(shù)倍,這樣我們?cè)趧?dòng)態(tài)規(guī)劃的迭代次數(shù)是商品個(gè)數(shù)m乘以錢數(shù)N的,所以我們可以把N/10,商品價(jià)格也除以10,這樣我們迭代次數(shù)只有m*N/10次,只有原來的的1/10次迭代,大大提升了迭代效率
?解決代碼:
import java.util.*;public class Main{public static void main(String args[]){Scanner sc = new Scanner(System.in);int N = sc.nextInt();int m = sc.nextInt();int[] v= new int[m];int[] p= new int[m];int[] q= new int[m];int[]hq1= new int[m+1];// 存放主件的附件下標(biāo)int[]hq2= new int[m+1];for(int i=0;i<=m;i++){hq1[i] = -1;hq2[i] = -1;}int[][]dp = new int[m+1][N/10+1];// 除以10減少動(dòng)態(tài)規(guī)劃迭代次數(shù)for(int i = 0;i<m;i++){v[i] = sc.nextInt()/10;p[i] = sc.nextInt();q[i] = sc.nextInt();if(q[i] !=0){if(hq1[q[i]]==-1){hq1[q[i]] =i;}else{hq2[q[i]] =i;}}}for(int i = 1;i <= m;i++){int tv=-1,tv1=-1,tv2=-1,tv3=-1,tdp=0,tdp1=0,tdp2=0,tdp3=0;tv=v[i-1];tdp=tv*p[i-1];if(hq1[i] != -1){tv1=tv+v[hq1[i]];tdp1 = tdp + v[hq1[i]]*p[hq1[i]];}if(hq2[i] != -1){tv2=tv+v[hq2[i]];tdp2 = tdp + v[hq2[i]]*p[hq2[i]];}if(hq1[i] != -1 && hq2[i] != -1){tv3=tv+v[hq1[i]]+v[hq2[i]];tdp3 = tdp + v[hq1[i]]*p[hq1[i]]+ v[hq2[i]]*p[hq2[i]];}for(int j=1;j<=N/10;j++){if(q[i-1] != 0){dp[i][j] = dp[i-1][j];}else{dp[i][j] = dp[i-1][j];if(j>=tv && tv!=-1){dp[i][j] = Math.max(dp[i][j],dp[i-1][j-tv]+tdp);}if(j>=tv1 && tv1!=-1){dp[i][j] = Math.max(dp[i][j],dp[i-1][j-tv1]+tdp1);}if(j>=tv2 && tv2!=-1){dp[i][j] = Math.max(dp[i][j],dp[i-1][j-tv2]+tdp2);}if(j>=tv3 && tv3!=-1){dp[i][j] = Math.max(dp[i][j],dp[i-1][j-tv3]+tdp3);}}}}System.out.println(dp[m][N/10]*10);} }總結(jié)
以上是生活随笔為你收集整理的牛客网-华为机试练习题 16 购物单的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言编程思想的题目,c语言方面毕业设计
- 下一篇: 大学物理复习笔记——静电场