Java、Android背包问题(二)——动态规划


前言

继上一篇背包问题–贪心算法,这一次我们来看看动态规划
对于动态规划,一开始看背包问题的时候直接接触的是动态规划
感觉也是比较简单的

题目的具体要求,详细看上一篇,这一篇我们讲述另一个方法

一、动态规划

动态规划需要我们找到最优解,并且可以避免重复的计算,节省时间

动态规划分析

**开始,我们先定义一些声明和变量
Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积
定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值
**
背包问题的动态规划,考虑的是 装和不装的问题,就是01背包问题

所以出现两种情况:
当不装的时候(背包容量比物体的重量小)此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j)
当装入背包,但是可能到达不了最优,也要考虑装和不装
即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
选取最大值,保证最优
V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i),但价值增加了v(i)

二、代码实现

1.主布局

相对于上次的贪心算法的布局,这次增加了动态规划

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/number"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="背包容量"
            android:imeOptions="actionDone"
            android:inputType="number" />
    </com.google.android.material.textfield.TextInputLayout>

    <!--
    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">

        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:imeOptions="actionDone"
            android:inputType="number"
            android:hint="物品个数"/>
    </com.google.android.material.textfield.TextInputLayout>
    -->

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_weight="1">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/weight"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="物品重量"
                android:imeOptions="actionNext"
                android:inputType="number" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:layout_weight="1">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/values"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="物品价值"
                android:imeOptions="actionNone"
                android:inputType="number" />
        </com.google.android.material.textfield.TextInputLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <com.google.android.material.button.MaterialButton
            android:id="@+id/define"
            style="@style/materialButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="确定"
            android:textColor="#CC9933"
            app:cornerRadius="12dp"
            app:strokeColor="#CC9933"
            app:strokeWidth="2dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="40dp"
            android:layout_marginRight="10dp"
            android:text="当前物品个数:"
            android:textColor="@color/black"
            android:textSize="17sp" />

        <TextView
            android:id="@+id/amount"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:textColor="@color/black"
            android:textSize="17sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <com.google.android.material.button.MaterialButton
            android:id="@+id/greed"
            style="@style/materialButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="贪心算法"
            android:textColor="#CC9933"
            app:cornerRadius="12dp"
            app:strokeColor="#CC9933"
            app:strokeWidth="2dp" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/dynamic"
            style="@style/materialButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="动态规划"
            android:textColor="#CC9933"
            app:cornerRadius="12dp"
            app:strokeColor="#CC9933"
            app:strokeWidth="2dp" />

        
    </LinearLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/goodsRecycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

这一次我还新增了一个物品的个数的显示,比较方便提醒现在有多少个物品
在这里插入图片描述

2.布局

这一个布局呢 是点击了按钮之后跳转活动的布局
这一次动态规划呢 我稍微对布局显示的东西写的复杂了一点
写了两个RecyclerView,不过其实大致是差不多的东西内容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".page.DynamicProgramming">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="20dp"
            android:layout_marginRight="20dp"
            android:text="背包容量:"
            android:textColor="@color/black"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/dynamicBackpack"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="20dp"
            android:layout_marginRight="20dp"
            android:text="" />
    </LinearLayout>

    <com.google.android.material.textview.MaterialTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="15dp"
        android:background="#FFF"
        android:text="放入背包的物品为:"
        android:textColor="@color/black"
        android:textSize="18sp" />

    <com.google.android.material.textview.MaterialTextView
        android:id="@+id/goodDynamic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="5dp"
        android:background="#FFF"
        android:text=""
        android:textColor="@color/black"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/dynamic_full"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/dynamic_best"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

在这里插入图片描述
左边的RecyclerView 我想用来显示全部物品的信息,右边的呢 就是装入背包的物品的信息,就是所谓的最优解

左边:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/dynamicFullCard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginBottom="3dp"
    app:cardCornerRadius="15dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:paddingLeft="10dp"
                android:text="物品的重量:" />

            <TextView
                android:id="@+id/dynamicWeight"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="10dp"
                android:text=""
                android:textSize="15sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:paddingLeft="10dp"
                android:text="物品的价值:" />

            <TextView
                android:id="@+id/dynamicValues"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="10dp"
                android:text=""
                android:textSize="15sp" />
        </LinearLayout>
    </LinearLayout>

</androidx.cardview.widget.CardView>

右边:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/dynamicBestCard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginBottom="3dp"
    app:cardCornerRadius="15dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginTop="10dp">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:paddingLeft="10dp"
                android:text="物品的重量:" />

            <TextView
                android:id="@+id/dynamicWeight"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="10dp"
                android:text=""
                android:textSize="15sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:paddingLeft="10dp"
                android:text="物品的价值:" />

            <TextView
                android:id="@+id/dynamicValues"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="10dp"
                android:text=""
                android:textSize="15sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical">

            <com.google.android.material.textview.MaterialTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:paddingLeft="10dp"
                android:lineHeight="20dp"
                android:text="第几个放入背包\n(最优解):" />

            <TextView
                android:id="@+id/dynamicBest"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="10dp"
                android:text=""
                android:textSize="15sp"
                android:layout_marginBottom="10dp"/>
        </LinearLayout>
    </LinearLayout>


</androidx.cardview.widget.CardView>

3.bean数据

因为我们要找到最优解,那么除了重量和价值之外,还要有一个属性来表示最优解 这里呢我就用best来表示

public class DynamicGood {

    private int weight;
    private int values;
    private int best;

    public DynamicGood() {
    }

    public DynamicGood(int weight, int values) {
        this.weight = weight;
        this.values = values;
    }

    public DynamicGood(int weight, int values, int best) {
        this.weight = weight;
        this.values = values;
        this.best = best;
    }
    //三个属性的get 和 set没有给出

这里 为什么我要写两个构造函数呢?
原因是:因为我们写的两个RecyclerView一个是全部物品,一个是最优解的物品,需要的参数是不一样的!

4.适配器

因为两个只是差一条best的属性,所以其实适配器几乎是一样的

public class DynamicBestAdapter extends RecyclerView.Adapter<DynamicBestAdapter.ViewHolder> {

    private Context context;
    private List<DynamicGood> list = new ArrayList<>();

    public DynamicBestAdapter(List<DynamicGood> list) {
        this.list = list;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (context == null) {
            context = parent.getContext();
        }
        
        //左边使用的cardView不一样
        View view = LayoutInflater.from(context).inflate(R.layout.recy_dynamic_best, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        DynamicGood dynamicGoodBest = list.get(position + 1);
        holder.dynamicWeight.setText(String.valueOf(dynamicGoodBest.getWeight()));
        holder.dynamicValues.setText(String.valueOf(dynamicGoodBest.getValues()));
 
		//左边RecyclerView不用最优解,去掉
       holder.dynamicBest.setText(String.valueOf(dynamicGoodBest.getBest()));
    }

    @Override
    public int getItemCount() {
        return list.size() - 1;
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        CardView cardView;
        TextView dynamicWeight;
        TextView dynamicValues;

		//左边RecyclerView 去掉dynamicBest
        TextView dynamicBest;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            cardView = (CardView) itemView.findViewById(R.id.dynamicBestCard);
            dynamicWeight = (TextView) itemView.findViewById(R.id.dynamicWeight);
            dynamicValues = (TextView) itemView.findViewById(R.id.dynamicValues);

			//左边去掉
            dynamicBest = (TextView) itemView.findViewById(R.id.dynamicBest);
        }
    }
}

这样 两个适配器 我们就写好了 就到我们的Activity了

5.DynamicProgramming Activity

建立模型,即求max(V1X1+V2X2+…+VnXn);
寻找约束条件,W1X1+W2X2+…+WnXn<capacity;
动态规划01背包问题 要保证装入物品的重量小于背包容量,并且价值要最大,有最优解

public class DynamicProgramming extends AppCompatActivity {
    private RecyclerView recyclerViewFull, recyclerViewBest;
    private DynamicFullAdapter dynamicFullAdapter;
    private DynamicBestAdapter dynamicBestAdapter;
    private List<DynamicGood> fullList = new ArrayList<>();
    private List<DynamicGood> bestList = new ArrayList<>();
    private TextView goodDynamic, dynamicBackpack;
    private int volume;     //背包大小,背包容量
    private int bestNumber = 0; //统计有多少个装入背包

    private int[][] dynamicProgramming;    //动态规划表

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dynamic_programming);

        init();     //初始化
        programming();  //动态规划
 
        bestSituation(goodsWeight.size() - 1, volume); //最优解情况
        print();
    }

    //打印
    private void print() {
        dynamicBackpack.setText(String.valueOf(volume));
        for (int i = 1; i <= goodsBest.size() - 1; i++) {
            if (goodsBest.get(i) == 1) {
                bestNumber++;   //统计最优解个数
                //显示的是最优解的下标
               
                goodDynamic.append(String.valueOf(i));
               
                goodDynamic.append(" ");
            }
        }
        //初始化数组
        DynamicGood[] fullDynamic;  //全部物品的显示
        DynamicGood[] bestDynamic;  //装入背包的物品的显示

        fullDynamic = new DynamicGood[goodsWeight.size()];
        fullDynamic[0] = new DynamicGood(0, 0);
        for (int i = 1; i <= goodsWeight.size() - 1; i++) {
            fullDynamic[i] = new DynamicGood(goodsWeight.get(i), goodsValues.get(i));
        }
        fullList.clear();
        for (int x = 0; x < fullDynamic.length; x++) {
            fullList.add(fullDynamic[x]);
        }

        bestDynamic = new DynamicGood[goodsBest.size()];    //size 5  所以 bestDynamic.length = 5
        int temp = 0;     //temp统计最优解的数量 初始化为0  数组第一个边界为0  当best == 1时候 temp++
        bestDynamic[temp] = new DynamicGood(0, 0, 0);
        for (int i = 1; i <= goodsBest.size() - 1; i++) {
         
            //先遍历 找到装入的物品 goodsBest赋值为1的
            //weight values best的下标
            if (goodsBest.get(i) == 1) {
                bestDynamic[temp += 1] = new DynamicGood(goodsWeight.get(i), goodsValues.get(i), i);
//                for (int j = 1; j <= bestNumber; j++) {
//                    bestDynamic[j] = new DynamicGood(goodsWeight.get(i), goodsValues.get(i), goodsBest.get(i));
//                }
            }
        }
        bestList.clear();
        for (int x = 0; x <= temp; x++) {
            bestList.add(bestDynamic[x]);
        }

        GridLayoutManager gridLayoutManagerFull = new GridLayoutManager(this, 1);
        GridLayoutManager gridLayoutManagerBest = new GridLayoutManager(this, 1);
        recyclerViewFull.setLayoutManager(gridLayoutManagerFull);
        recyclerViewBest.setLayoutManager(gridLayoutManagerBest);
        dynamicFullAdapter = new DynamicFullAdapter(fullList);
        dynamicBestAdapter = new DynamicBestAdapter(bestList);
        recyclerViewFull.setAdapter(dynamicFullAdapter);
        recyclerViewBest.setAdapter(dynamicBestAdapter);
    }

    //初始化
    private void init() {
        volume = getIntent().getIntExtra("goodsVolume", 0);      //背包容量传值
        //volume = getIntent().getDoubleExtra("goodsVolume",0);
        dynamicProgramming = new int[goodsWeight.size()][volume + 1];             //动态规划表
     
        goodDynamic = (TextView) findViewById(R.id.goodDynamic);
        dynamicBackpack = (TextView) findViewById(R.id.dynamicBackpack);
        recyclerViewFull = (RecyclerView) findViewById(R.id.dynamic_full);
        recyclerViewBest = (RecyclerView) findViewById(R.id.dynamic_best);

        //先保证最优解动态数组全部为0
        for (int i = 1; i <= goodsWeight.size() - 1; i++) {
            goodsBest.add(0);
         
        }
    }

    //动态规划
    private void programming() {
        for (int i = 1; i <= goodsWeight.size() - 1; i++) {  //i为第几个物品
            for (int j = 1; j <= volume; j++) {       //j当前背包容量,相当于背包容量一点一点加,当满足能装入物品时候则开始判断是否装入
                if (j < goodsWeight.get(i)) {
                    //因为容量不够装入物品,所以动态规划表与前一个物品的一样,[前i个物品最佳组合对应的价值][当前背包容量]
                    //因为不装入物品,所以前i个物品的最佳组合对应的价值相等
                    dynamicProgramming[i][j] = dynamicProgramming[i - 1][j];
                  
                } else {
                    //当装入物品时候,判断是上一个物品的价值大,还是装入后价值大,求出最优解
                    dynamicProgramming[i][j] = Math.max(dynamicProgramming[i - 1][j], dynamicProgramming[i - 1][j - goodsWeight.get(i)] + goodsValues.get(i));
                 
                }
            }
        }
    }

    //找最优解
    private void bestSituation(int i, int j) {
    
        if (i - 1 >= 0) {
          
            //传入的参数是最后一个物品的序号i 容量j
            if (dynamicProgramming[i][j] == dynamicProgramming[i - 1][j]) {    //如果动态规划表中 当前物品和前一个物品的价值相等
                // 则表示没有装入物品
               
                goodsBest.set(i, 0);             //最优解标记为0 表示没有装入
              
                bestSituation(i - 1, j);           //递归再看下一个物品是否是最优解
            } else if (j - goodsWeight.get(i) >= 0 && dynamicProgramming[i][j] == dynamicProgramming[i - 1][j - goodsWeight.get(i)] + goodsValues.get(i)) {
                //如果背包容量够并且装入后达到最优价值
              
                goodsBest.set(i, 1);     //则标记为最优解
              
                bestSituation(i - 1, j - goodsWeight.get(i));    //下一个物品
            }
        }
    }
}

首先就是初始化,这个都是绑定实例,绑定控件的一些代码,还有从Mainactivity将背包容量传过来,这都是跟之前贪心算法一样
然后最优解我也是用动态数组来存储的,之前在贪心算法那篇有说过,动态数组开始的第一个元素为0,为了方便动态规划
在之前的类Goods 中多定义一个动态数组Best

//Goods
    //用于动态规划,保存最优解,看哪个物品放入, 最优解情况
    public static ArrayList<Integer> goodsBest = new ArrayList<Integer>();

然后进行动态规划programming() 对比是否装入物品,装入物品时候是否是价值最大

然后是找最优解,我们将装入的物品在Best当中标记为1没装入的物品则是0,等到打印函数print() 也依据Best当中是否为1,来让他显示在我们之前写的右边的RecyclerView当中
最优解,相当于是将动态规划表倒着回去找 从最后一个放入的回头找
如果当前物品和前一个物品价值相等,则没有装入,然后递归下一个
如果背包容量够并且装入后达到最优价值,则为最优解


关于打印部分,也是跟之前一样将对象new出来添加到list里面
不过在最优解的添加到list的部分,因为要考虑是否是最优解,需要判断goodsBest的元素是否等于1,
并且注意,我们返回的是最优解的下标,来以此知道是第几个物品是最优解

6.MainActivity

我们新增加了最优解的数组,也需要开始元素为0
大体上除了点击事件 没有什么变化

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    private RecyclerView recyclerView;
    private RecyclerViewAdapter recyclerViewAdapter;
    private List<Data> dataList = new ArrayList<>();

    private TextInputEditText number;       //容量
    private TextInputEditText weight;       //重量
    private TextInputEditText values;       //价值
    private Button define;
    private TextView amount;                //物品个数(就用int类型)
    private int goodsAmount = 0;                //物品个数(就用int类型)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 1);
        recyclerView.setLayoutManager(gridLayoutManager);
        recyclerViewAdapter = new RecyclerViewAdapter(dataList);
        recyclerView.setAdapter(recyclerViewAdapter);
    }

    private void init() {
        goodsWeight.add(0);
        goodsValues.add(0);
        goodsScale.add(0.0);           //初始化边界条件,关乎之后数组边界溢出问题
        goodsBest.add(0);
        Log.d("size","size :"+goodsBest.size());
        recyclerView = (RecyclerView) findViewById(R.id.goodsRecycler);
        number = (TextInputEditText) findViewById(R.id.number);
        weight = (TextInputEditText) findViewById(R.id.weight);
        values = (TextInputEditText) findViewById(R.id.values);
        amount = (TextView) findViewById(R.id.amount);
        define = (Button) findViewById(R.id.define);
        define.setOnClickListener(this);
        Button greed = (Button) findViewById(R.id.greed);
        greed.setOnClickListener(this);
        Button dynamic = (Button) findViewById(R.id.dynamic);
        dynamic.setOnClickListener(this);
      
        amount.setText(String.valueOf(goodsAmount));
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.define:
                //进行判断,保证两个输入框都有值
                if (weight.getText() == null || weight.getText().length() == 0 || values.getText() == null || values.getText().length() == 0) {
                    //未输入完全则提示输入不完全
                    Toast.makeText(this, "请完整输入物品重量和价值", Toast.LENGTH_SHORT).show();
                } else {
                    int n = Integer.parseInt(weight.getText().toString());  //获取物品重量输入值
                    int m = Integer.parseInt(values.getText().toString());  //获取物品价值输入值
                    Data goods = new Data(n, m);        //创建Data对象

                    //dataList.add(goods);
                    recyclerViewAdapter.add(goods);     //加入适配器Adapter 用于显示
                    goodsWeight.add(n);                 //将值保存入动态数组
                    goodsValues.add(m);                 //将值保存入动态数组
                    Log.d("111", "...." + goodsWeight.size());    //测试保证动态数组的长度使用
                    Log.d("111", "......" + goodsWeight.get(1));   //测试保证动态数组的取值使用
                    weight.setText("");
                    values.setText("");                 //保证每次输入后,输入框的值清空保证下次输入
                    goodsAmount++;
                    amount.setText(String.valueOf(goodsAmount));

                    //保证每次输入后,取消输入框光标

                    weight.setImeOptions(EditorInfo.IME_ACTION_NONE);
                    values.setImeOptions(EditorInfo.IME_ACTION_NONE);
                }
                break;
            case R.id.greed:
                //判断保证输入背包容量,不至于让计算时候背包容量空值
                //在上面已经对两个动态数组进行了边界初始化,所以数组长度已经是1
                if (number.getText() == null || number.getText().length() == 0 || goodsWeight.size() == 1 || goodsValues.size() == 1) {
                    //信息提示
                    Toast.makeText(this, "请完整输入背包容量或者物品重量和价值", Toast.LENGTH_SHORT).show();
                } else {
                    //到下一个活动求解贪心算法
                    Intent pageGreed = new Intent(MainActivity.this, PageGreed.class);

                    //将背包容量传值入贪心算法的活动
                    int volume = Integer.parseInt(number.getText().toString());     //获取背包容量输入框的值
                    pageGreed.putExtra("goodsVolume", volume);       //Intent对象.putExtra(键值,实际值)
                    //键值类似指针用于找到值

                    startActivity(pageGreed);
                }
                break;
            case R.id.dynamic:
                if (number.getText() == null || number.getText().length() == 0 || goodsWeight.size() == 1 || goodsValues.size() == 1) {
                    //信息提示
                    Toast.makeText(this, "请完整输入背包容量或者物品重量和价值", Toast.LENGTH_SHORT).show();
                } else {
                    Intent dynamicProgramming = new Intent(MainActivity.this, DynamicProgramming.class);

                    int volume = Integer.parseInt(number.getText().toString());
                    dynamicProgramming.putExtra("goodsVolume", volume);

                    startActivity(dynamicProgramming);
                }
                break;
          
        }
    }
}

也是保证了有完整的输入,然后传值
具体难点在于理解,动态规划最优解和动态规划表
因为要求可视化,对于动态规划的打印显示也有一定难点


对于动态规划,其实算法本身不难,我感觉自己写Android代码,对于可视化的要求还是有一点难度的

最后放一张丑丑的运行结果:

在这里插入图片描述

总结

目前 背包问题到现在已经有了贪心算法和动态规划

自己在写代码的时候 比较迷糊的也就是关于最优解的问题
还有还有最绕的就是关于RecyclerView的list的添加的问题
因为需要new新的来add到list里面,但是又有限制best需要等于1

PS:这部分写list的时候真的是写着写着头脑迷糊 有点发晕,就很绕

之后还会有蛮力法、贪心算法求解01背包问题近似解等等方法
(具体可以相互学习交流)

来日方长
to be continued……

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iㅤ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值