ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

存钱罐最小值问题(java)

2021-11-28 21:59:06  阅读:152  来源: 互联网

标签:java scanner int coins 最小值 存钱罐 public dp


1.主观题 (100分)

实验六:使用动态规划算法解决存钱问题(完成实验报告三、四、五、六的内容)


一、实验目的

       练习使用动态规划算法解决实际问题(使用Java语言实现)。

二、实验内容

【问题描述】

给定一个空存钱罐的重量和这个存钱罐最多能装进去的重量,现在需要在不打破这个存钱罐的情况下猜测里面最少的钱。每种钱的数量不做限制,条件是必须装满,同时给出每种钱币的价值和重量。 

【输入】

输入的第一行数据包含整数T,表示测试用例的数量。每个测试用例的第一行都包含两个整数e和f(1<=e<=f<=10000),分别表示空存钱罐和装满硬币的存钱罐的重量(以克记)。第二行包含一个整数n(1<=n<=500),表示硬币的总数量。接下来的n行每行都包含两个整数p和w,分别表示硬币的面值和重量。

【输出】

对每个测试用例,都输出一行,包含”存钱罐内的最小金额是 x“,其中x是存钱罐内的最小金额。若无法确定,则输出”这是不可能的“

【输入输出示例】

样例输入:

 10 110 

 2 

 1 1 

 30 50 

 10 110 

 2 

 1 1 

 50 30 

 1 6 

 2 

 10 3 

 20 4

样例输出:

存钱罐内的最小金额是60

存钱罐内的最小金额是100

这是不可能的

【思路提示】

这是一个完全背包问题。

三、 程序代码

(1)MinWeigh

package maxweightminvalue;

import java.util.Scanner;

public class MinWeight {
        private int coinSort;//硬币的种类
        private int e;//存钱罐自身重量
        private int f;//存钱罐装满最大的重量
        private int v;//存钱罐的容量
        private int[] dp=new int[10001];//dp数组
        Coin[] coins;//硬币的面值和重量数组

        public void inputData() {
            int exit = 1;
            Scanner scanner = new Scanner(System.in);
            //System.out.println("请输入测试的次数:");
            while (exit==1) {
                    coins = new Coin[1000];
                    System.out.println("请输入存钱罐自身重量和装满最大的重量:");
                    e = scanner.nextInt();
                    f = scanner.nextInt();
                    v = f - e;
                    System.out.println("请输入硬币的种类:");
                    coinSort = scanner.nextInt();
                    System.out.println("请输入每种硬币的面值和重量:");
                    for (int i = 0; i < coinSort; i++) {
                        coins[i] = new Coin();
                        coins[i].value = scanner.nextInt();
                        coins[i].weight = scanner.nextInt();
                    }
                display();
                System.out.println("是否想继续测试(继续测试输入1,退出请输入0):");
                exit=scanner.nextInt();
            }
        }

        public int load(){
            dp[0]=0;
            for(int i=1;i<=v;i++){
                dp[i]=500000001;//设置数组中能设置的最大值,便于比较筛选出最小值
            }
            for(int i=0;i<coinSort;i++){
                for(int j=0;j<=v;j++){
                    if (j-coins[i].weight<0)
                        dp[j]=dp[j];//因为装不下所以没有变化
                    else//能装下则需要进行装下物品的最小值比较
                        dp[j]=Math.min(dp[j],dp[j-coins[i].weight]+coins[i].value);//状态转移方程
                }
            }
            return dp[v];
        }

        public void display(){
                if(load()!=500000001){
                    System.out.println("存钱罐内的最小金额是"+load());
                }
                else {//数组最后值没有变化则说明当前金币种类与金币质量不匹配
                    System.out.println("这是不可能的");
                }
        }



    }



(2)Coin

package maxweightminvalue;

public class Coin {
    public int value;
    public int weight;
    public int number;
}

(3)TestMinWeight

package test;

import maxweightminvalue.MinWeight;

public class TestMinWeight {
    public static void main(String[] args) {
        MinWeight minWeight =new MinWeight();
        minWeight.inputData();
    }
}

四、 实验结果(含程序运行截图)

EM%M4R(`89{6U`QCS~12_2D.png

五、 出现问题及解决方法

本次实验为完全背包问题与01背包不同的是一种物品可以放入多个,所以我们再装入物品的时候需要考虑装入该物品的数量,正常情况下是求能装入背包的最大值但是本题是装入的最小值,所以再求状态转移方程时有困难,以及在求解数组时候的思想比较难考虑到,也是参考了网上的思路后才开始动手的。下面说一下不同于最大值的点:

(1)开始时不同于其他的求解最大值的背包问题是要对dp数组进行赋值为0的初始化而是进行对于dp数组中的每一个元素来复制成该整型变量所能承受的最大值。

for(int i=1;i<=v;i++){
   dp[i]=500000001;//设置数组中能设置的最大值,便于比较筛选出最小值
}

因为要筛选出最小值所以赋值为其他怕影响最小值比较时因为原始数组初始化存放数据的影响导致比较错误。

(2)求解状态转移方程

       求解状态方程网上有很多做法比如在ij的·循环内再加一个对应的放入某种物品数量的k变量来进行记录但是适应于最大值不适应于最小值,所以问题很多,修改的时候不能单纯的进行将最大值改成最小值,所以在查找资料后发现了下面的状态方程:

dp[j]=Math.min(dp[j],dp[j-coins[i].weight]+coins[i].value);//状态转移方程

       该状态转移方程为循环求解给出的钱币种类以及质量,比较更小的那个进行存放。而且是一种钱币比较一次,但是最终结果都存放在一维的dp数组中,最后循环到最后的值如果能正好将存钱罐体积填满则dp数组的最后一个值不为500000001,如果没办法填满则最后的dp数组的值仍然为500000001没有变化,则给出的钱币种类不能将体积填满,所以是不可能的。

六、 实验心得

本次实验心得为算法还是要多拓展自己的思路要有自己思考的过程,争取有一天能够自己想出好的算法。

 第一篇博客,确实有在网上查资料的成分,大家有什么问题欢迎在评论区留言呀,有什么好的想法我也想学习一下~


标签:java,scanner,int,coins,最小值,存钱罐,public,dp
来源: https://blog.csdn.net/shixixiya6/article/details/121598542

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有