题解 | #购物单#

购物单

http://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4

import java.util.Scanner;

public class Main { static int N; static int m; static int[] v =new int[60]; static int[] p =new int[60]; static int[] q =new int[60]; static int[] v1 =new int[60]; static int[] p1 =new int[60]; static int[] q1 =new int[60]; static int s[][]=new int[60][3200];//满意度s[i][j],表示从第i个物品看起,剩余10j钳的最大满意度。 static int count=0;//主件数量

public static void main(String[] args) {
    //输入
    Scanner sc = new Scanner(System.in);
    N=sc.nextInt();
    m=sc.nextInt();

    for (int i = 0; i < m; i++) {
        v[i]=sc.nextInt();
        p[i]=sc.nextInt();
        q[i]=sc.nextInt();
        if(q[i]==0) {
            count++;
        }
    }
    //动态规划解决最大满意度问题
    //最优子结构:
    //若(y1,...,yn)是最优解,(y2,...,yn)应该是相应子问题的最优解。
    //递归关系:
    //s[i][j]=(本就拿不了i,即v[i]>10j)s[i+1][j];
    //或者y[q[i]]==0,没拿主件。这里有问题,与范围外的数字相关了,因此需要数据预处理

    //预处理:将附件放在主件后,以便在不拿的时候连续的舍弃附件。
    //创建另一个相同大小的数组,遍历多次,选出主件填入后,将附件跟在其后,直到全部转移。
    boolean flag=true;//循环是否停止
    int dst=0;//是否在找附件,以及正在找的附件从属主件编号
    int mainPosition=0;//主件在新数组中的位置
    int j=0;//新数组的指针
    while (flag){
        flag=false;
        for (int i = 0; i < m; i++) {
            if (v[i]!=0)flag=true;
            if (dst!=0){
                if (q[i]==dst&&v[i]!=0){
                    insert(i,j, mainPosition+1);
                    j++;
                }
            }
            if (dst==0){
                if (q[i]==0&&v[i]!=0){
                    dst=i+1;
                    mainPosition=j;
                    insert(i,j);
                    j++;
                    i=-1;
                }
            }
        }
        dst=0;
    }

    //else (不拿i,且i为附件) s[i+1][j];
    //  (不拿i,且i为主件) s[i+x][j]
    //  (拿i) s[i+1][j-v[i]/10]+v[i]*p[i] 三者的最大值。
    //用备忘录方法求出s[0][N/10]
    int rs=result(0,N/10);
    System.out.println(rs);

    sc.close();
}

private static int result(int i, int j) {
    if (s[i][j]!=0)return s[i][j];
    if (i>=m-1){//走到最后一个物品
        if (v1[m-1]<=10*j){
            s[m-1][j]=v1[m-1]*p1[m-1];
        }
        else{
            s[m-1][j]=0;
        }
        return s[m-1][j];
    }
    if (v1[i]>10*j&&q1[i]!=0){
        s[i][j]=result(i+1,j);
        return s[i][j];//拿不了且为附件
    }
    if (v1[i]>10*j&&q1[i]==0){//拿不了且为主件
        int k=i+1;
        while(q1[k]==i+1){
            k++;
        }
        s[i][j]=result(k,j);
        return s[i][j];
    }
    //拿的了的2种情况
    if (q[i]==0){//是主件
        int k=i+1;
        while(q1[k]==i+1){
            k++;
        }
        s[i][j]=Math.max(result(k,j),result(i+1,j-v1[i]/10)+v1[i]*p1[i]);
        return s[i][j];
    }
    if(q[i]!=0){//是附件
        s[i][j]=Math.max(result(i+1,j),result(i+1,j-v1[i]/10)+v1[i]*p1[i]);
        return s[i][j];
    }
    return -1;
}

private static void insert(int i, int j) {
    v1[j]=v[i];
    p1[j]=p[i];
    q1[j]=0;
    v[i]=0;//标记为清空

}

//将原数组的i,插入到新数组的j的位置,并删除原元素
private static void insert(int i, int j,int mainPosition) {
    v1[j]=v[i];
    p1[j]=p[i];
    q1[j]=mainPosition;
    v[i]=0;//标记为清空
}

}

全部评论

相关推荐

02-01 19:48
门头沟学院 Java
神哥了不得:(非引流)直接暑期吧,没时间日常了,老鱼简历把水印去了,或者换个模板,简历字体大小都不太行,建议换2个高质量的项目,面试应该还会再多一些
点赞 评论 收藏
分享
01-14 12:08
门头沟学院 Java
神哥了不得:(非引流)1.既然发出来了简历,就稍微提一点点小建议,确实简历很不错了,练手项目可以换一些质量高的,工作内容,可以加上一些量化指标,比如第一条系统响应速度由多少变成多少,减少了百分之多少,第4条就很不错。2.广投,年前实习招募比较少了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务