追加条件を伴う0-1ナップサック問題

序文

水に関するブログ投稿は、私がまだ生きていることを証明しています〜

問題の説明(0-1ナップサック問題)

さて、最初にバックパック問題について話しましょう。
まず第一に、バックパックの問題は、限られたバックパックでは、できるだけ多くのアイテムがあり、各アイテムには独自の品質と価値があるため、価値を最大化する必要があります!

それでは、ナップサック問題が動的計画問題になる理由について最初に説明しましょう。動的計画法には明らかな特徴があります。現在の状態は、フィボナッチ数列などの前の状態に依存します(もちろん、フィボナッチ数列については、マトリックスを使用できます)。問題をスピードアップするためのパワー乗算)。次に、バックパック問題では、明らかに、次のアイテムを配置するかどうかは、現在のバックパックの容量と前のアイテムが配置されるかどうかに依存し、配置後の値は最大です(前のアイテムは配置されません、前のアイテムは配置されます)。 、前のアイテムは前のアイテムと前のアイテムに依存しているので、これはフィボナッチ数列の問題である階段を上るのと同じであることがわかります。このように、ナップサック問題は、元の単純な動的計画法、つまり追加の制約を前提として、実際に最大化(最小化)制約を追加していることを理解しています。

次に、ナップサック問題を理解した後、青いブリッジカップ問題で見たナップサック問題と同様の問題について話しましょう。最初の最も明白な問題は、グリッドを歩く問題です。グリッドには特定の値があります。次に、この値を最大にします。

例えば:

image.png

これについてはどうですか、あなたはそれをどのように言いますか、最大の価値を達成するために、限られたスペース、または制限内に最も多くのアイテムを配置することです。

メーター別

これを理解するには、まだテーブルを作成する必要があります。

ここに画像の説明を挿入

さらに、それぞれ重みと値を表す2つの配列があります。

ここで言葉を繰り返したくはありません。前の言葉は書かれています。
今日は、追加の条件を実行する方法についてのみ説明します。

トピック

ここに画像の説明を挿入

アイデア

最初は明らかにナップサック問題ですが、ここで対処する条件がいくつかあります。

バックパックを考えるとき、そのバックパックの容量だけを考慮する必要があることがわかります。したがって、ここでは、これを考慮するだけでなく、交差できない状態も考慮する必要があります。

次に、ここで質問があります。つまり、dpのときに選択を行うので、どの製品を選択したかをどのように知ることができますか。したがって、この0-1ナップサック問題に精通している必要があります。そして、それに対処する方法を知った後、私たちはそれを行うことができます。

コード

package com.huterox.testweek02;

import java.util.ArrayList;
import java.util.Scanner;

public class week209 {
    
    
    //目前的想法就是暴力搜索

//6
//1 1 2
//1 4 2
//1 7 2
//4 1 2
//4 4 2
//4 7 2


    static ArrayList<ArrayList<Integer>> trees = new ArrayList<>();

    public static void main(String[] args) {
    
    
        //初始化,我们把这个当作有约束的0-1背包问题
        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));
    }
}

3本の木135は
ここに画像の説明を挿入
大丈夫で、水が流れていることがわかります〜

おすすめ

転載: blog.csdn.net/FUTEROX/article/details/123619416