题解 | #购物单#
购物单
http://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4
解题方法
定义数据结构
- 明显看出需要定义Good类,包含v,p,q,fj1,fj2这几个字段,默认字段值为0.为了方便后续构造,实现有参构造函数和无参构造函数。(注意:无参构造函数容易漏掉)
- Good[] 来存储1~m+1行数据。(注意:最好把Good[] goods=new Good[m+1],否则后续操作容易数组越界)
动态规划
- 问题是求最值,首先想到动态规划
- 题目具有重叠子问题,明显的状态是总钱数N与可购买的数量m,又由于需要实时改变Good,定义dp(int N,Good[] goods)
输入字段处理
- 采用Scanner和string.split和Integer.valueOf处理输入字段。(注意:不要写while(sc.hasNextLine()),不然处理会出问题)
- 对于附件Good要找到主件Good对应字段初始化(注意:记得new Good())
代码思路
- 定义dp[N+1][goods.length],base case可以简单理解为总钱数为0或可购买数量为0时,dp[][]也为0
- 双层for循环遍历,讨论几种情况,求最大值: 2.1 是附件 2.2 是主件 2.2.1 是主件没有附件 2.2.2 是主件有附件1 2.2.3 是主件有附件2 2.2.4 是主件有附件1和附件2
import java.util.*;
public class Main{
static class Good{
public int v;
public int p;
public int q;
public int fj1=-1;
public int fj2=-1;
public Good(int v,int p,int q){
this.v=v;
this.p=p;
this.q=q;
}
public Good(){
}
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
String firstLine=sc.nextLine();
String[] split=firstLine.split(" ");
int N=Integer.valueOf(split[0]);
int m=Integer.valueOf(split[1]);
Good[] goods=new Good[m+1];
for(int i=1;i<m+1;i++){
String otherLine=sc.nextLine();
String[] split2=otherLine.split(" ");
int v=Integer.valueOf(split2[0]);
int p=Integer.valueOf(split2[1]);
int q=Integer.valueOf(split2[2]);
if(goods[i]!=null){
goods[i].v=v;
goods[i].p=p;
goods[i].q=q;
}else{
goods[i]=new Good(v,p,q);
}
// 设置主件的附件
if(goods[i].q>0){
if(goods[goods[i].q]==null){
goods[goods[i].q]=new Good();
}
if(goods[goods[i].q].fj1==-1){
goods[goods[i].q].fj1=i;
}else{
goods[goods[i].q].fj2=i;
}
}
}
dp(N,goods);
}
public static void dp(int N,Good[] goods){
int[][] dp=new int[N+1][goods.length];
for(int i=1;i<goods.length;i++){
int v=-1,v1=-1,v2=-1,v3=-1,temp=-1,temp1=-1,temp2=-1,temp3=-1;
v=goods[i].v;
temp=v*goods[i].p;
if(goods[i].fj1!=-1&&goods[i].fj2!=-1){
v3=v+goods[goods[i].fj1].v+goods[goods[i].fj2].v;
temp3=temp+goods[goods[i].fj1].v*goods[goods[i].fj1].p+goods[goods[i].fj2].v*goods[goods[i].fj2].p;
}
if(goods[i].fj1!=-1){
v1=v+goods[goods[i].fj1].v;
temp1=temp+goods[goods[i].fj1].v*goods[goods[i].fj1].p;
}
if(goods[i].fj2!=-1){
v2=v+goods[goods[i].fj2].v;
temp2=temp+goods[goods[i].fj2].v*goods[goods[i].fj2].p;
}
for(int j=1;j<N+1;j++){
if(goods[i].q>0){
dp[j][i]=dp[j][i-1];
}else{
dp[j][i]=dp[j][i-1];
if(j>=v&&v!=-1)dp[j][i]=Math.max(dp[j][i],dp[j-v][i-1]+temp);
if(j>=v1&&v1!=-1)dp[j][i]=Math.max(dp[j][i],dp[j-v1][i-1]+temp1);
if(j>=v2&&v2!=-1)dp[j][i]=Math.max(dp[j][i],dp[j-v2][i-1]+temp2);
if(j>=v3&&v3!=-1)dp[j][i]=Math.max(dp[j][i],dp[j-v3][i-1]+temp3);
}
}
}
System.out.println(dp[N][goods.length-1]);
}
}