前言
水一篇博文证明我还活着~
问题描述(0-1背包问题)
ok,咱们先来说说这个背包问题是怎么样的呢。 首先背包问题就是,在一个有限的背包内,尽可能去装下更多的物品,每个物品都是有自己的质量和价值的,我们要让价值最大化!
那么在这里我们先来说说,为什么背包问题可以是一个动态规划的题目,对于动态规划有一个明显的特征,当前状态取决于上一个状态,例如斐波那契数列(当然关于斐波那契数列我们又可以使用矩阵幂乘法来加速解决问题)。那么在背包问题里面,显然,下一个物品要不要放置,取决于当前的背包容量和上一个物品有没有放置,之后放置之后的值就是 max(没有放置上一个物品,放置了上一个物品)而,上一个物品又是取决于上上个物品和上物品,这样我们发现这个就相当于变成了走楼梯,斐波那契数列的问题。这样一来我们就懂了,背包问题其实就是在原来简单的动态规划的前提下,加入了最大化(最小化)的约束,也就是多加了一个约束!
那么在理解了背包问题之后,我们来说说在蓝桥杯题目里面我见到的类似背包问题的题目,首先最明显的就是那个走格子问题,在格子上面有一定的value,然后让这个value最大。
例如:
那这个呢,怎么说呢,就是在有限的空间内,或者是一个限制之内,放置最多的物品去达到最大的价值。
打表
想要搞清楚这个问题呢,咱们还是得打表。
此外咱们还有两个数组分别表示重量和价值。
这里的话我不太想了复述了,前面的话是有写过的。 我今天这里只说一下那个附加条件的怎么做。
题目
思路
首先很明显是个背包问题,但是这里有些个条件要处理一下。
原来我们考虑背包的话只是需要考虑那个背包的容量,那么这里的就是不仅要考虑这个,还要考虑那个不能相交的条件。
然后在这里引出了一个问题,就是我们在dp的时候是在做选择,那么我如何知道我选择了哪些商品的问题。所以需要你对这个0-1背包问题比较熟练。然后知道如何处理之后,咱们就能够动手了。
代码
package com.huterox.testweek02;
import java.util.ArrayList;
import java.util.Scanner;
public class week209 {
static ArrayList<ArrayList<Integer>> trees = new ArrayList<>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] w = new int[n];
int totalArea = 0;
for (int i=0;i<n;i++){
ArrayList<Integer> temp = new ArrayList<>();
int row = scanner.nextInt();
int col = scanner.nextInt();
int r = scanner.nextInt();
totalArea+=r*r;
temp.add(row);
temp.add(col);
temp.add(r);
w[i] = r*r;
trees.add(temp);
}
int[] dp = new int[totalArea+1];
int[] place = new int[n];
dp[0]=0;
for (int i=0;i<trees.size();i++){
for (int j=totalArea;j>=w[i];j--) {
if (i == 0) {
dp[j] = Math.max(dp[j], dp[j - w[i]] + w[i]);
place[i] = i;
}
else {
if(j - w[i]>=0)
{
int lay_now = dp[j - w[i]] + w[i];
if(lay_now>=dp[j]){
boolean flag = true;
for (int k=0;k<=i-1;k++){
if(!is_vaild(trees.get(i),trees.get(place[k]))){
flag = false;
}
}
if(flag){
place[i] = i;
dp[j] = lay_now;
}else
place[i] = place[i-1];
}
else {
dp[j] = dp[j];
place[i] = place[i-1];
}
}
}
}
}
System.out.println(dp[totalArea]);
System.out.println("种了这几颗树");
for (int s : place) {
System.out.printf("%d--",s);
}
}
public static boolean is_vaild(ArrayList<Integer> last,ArrayList<Integer> now){
double cha_x = (double)last.get(0) - now.get(0);
double cha_y = (double)last.get(1)-now.get(1);
double distance = (double)last.get(2)+last.get(2);
return (Math.pow(cha_x, 2) + Math.pow(cha_y, 2) >= Math.pow(distance, 2));
}
}
可以看到种了1 3 5这三棵树 ok, 水玩了~
|