n_toshi max_t p1,1 p1,2 ・・・ p1,max_t // 1 番目の投資先によって得られる利益 p2,1 p2,2 ・・・ p2,max_t // 2 番目の投資先によって得られる利益 ・・・ pn_toshi,1 pn_toshi,2 ・・・ pn_toshi,max_t
3 4 8 18 22 24 // 1 番目の投資先に 1 単位投資するとその利益は 8,2 単位投資するとその利益は 18,・・・ 3 6 9 12 // 2 番目の投資先に 1 単位投資するとその利益は 3,2 単位投資するとその利益は 6,・・・ 6 7 8 10 // ・・・
4 6 2 0 0 0 0 0 // 1 番目の品物の重さは 1 で,その効用は 2 0 0 5 0 0 0 // 2 番目の品物の重さは 3 で,その効用は 5 0 0 4 0 0 0 // 3 番目の品物の重さは 3 で,その効用は 4 0 0 3 0 0 0 // 4 番目の品物の重さは 3 で,その効用は 3
/***************************************************/ /* 動的計画法:資源配分問題(0-1 ナップザック問題)*/ /* ー投資先(品物)毎のデータを出力したい場合ー */ /* coded by Y.Suganuma */ /***************************************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) throws IOException { // データの入力と領域の確保 Scanner sc = new Scanner(System.in); int n_toshi = sc.nextInt(); // 投資先数(品物数) int max_t = sc.nextInt(); // 最大投資額(最大重量) max_t++; // 投資を行わない(品物を入れない)場合を含めるため int table[][] = new int [n_toshi][max_t]; // 投資額と利益(重さと効用) int rieki[][] = new int [n_toshi][max_t]; // 投資した際の利益(品物を入れた際の効用) int prev[][] = new int [n_toshi][max_t]; // 前段までの投資額(前段までの重さ) for (int i1 = 0; i1 < n_toshi; i1++) { table[i1][0] = 0; for (int i2 = 1; i2 < max_t; i2++) table[i1][i2] = sc.nextInt(); } // 動的計画法 // 初期設定(1段目) for (int i1 = 0; i1 < max_t; i1++) { rieki[0][i1] = table[0][i1]; prev[0][i1] = -1; } // 2段目以降 for (int i1 = 1; i1 < n_toshi; i1++) { for (int i2 = 0; i2 < max_t; i2++) { rieki[i1][i2] = rieki[i1-1][i2]; prev[i1][i2] = prev[i1-1][i2]; } for (int i2 = 0; i2 < max_t; i2++) { for (int i3 = 0; i2+i3 < max_t; i3++) { if (rieki[i1-1][i3]+table[i1][i2] > rieki[i1][i2+i3]) { rieki[i1][i2+i3] = rieki[i1-1][i3]+table[i1][i2]; prev[i1][i2+i3] = i3; } } } } // 結果の出力 int k = -1, max = -1; for (int i1 = 0; i1 < max_t ; i1++) { if (rieki[n_toshi-1][i1] > max) { max = rieki[n_toshi-1][i1]; k = i1; } } System.out.printf("最大利益(最大効用) %d\n", max); for (int i1 = n_toshi-1; i1 > 0; i1--) { int k1 = 0; if (rieki[i1][k] != rieki[i1-1][k]) { k1 = k - prev[i1][k]; k = prev[i1][k]; } System.out.printf(" 投資先(品物) %d 投資単位(重さ) %d 利益(効用) %d\n", i1+1, k1, table[i1][k1]); } System.out.printf(" 投資先(品物) 1 投資単位(重さ) %d 利益(効用) %d\n", k, table[0][k]); } }
/***************************************************/ /* 動的計画法:資源配分問題(0-1 ナップザック問題)*/ /* ー投資先(品物)毎のデータを必要としない場合ー */ /* coded by Y.Suganuma */ /***************************************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) throws IOException { // データの入力と領域の確保 Scanner sc = new Scanner(System.in); int n_toshi = sc.nextInt(); // 投資先数(品物数) int max_t = sc.nextInt(); // 最大投資額(最大重量) max_t++; // 投資を行わない(品物を入れない)場合を含めるため int table[][] = new int [n_toshi][max_t]; // 投資額と利益(重さと効用) int rieki[][] = new int [2][max_t]; // 投資した際の利益(品物を入れた際の効用) for (int i1 = 0; i1 < n_toshi; i1++) { table[i1][0] = 0; for (int i2 = 1; i2 < max_t; i2++) table[i1][i2] = sc.nextInt(); } // 動的計画法 // 初期設定(1段目) int k1 = 0, k2 = 1; for (int i1 = 0; i1 < max_t; i1++) rieki[0][i1] = table[0][i1]; // 2段目以降 for (int i1 = 1; i1 < n_toshi; i1++) { for (int i2 = 0; i2 < max_t; i2++) rieki[k2][i2] = rieki[k1][i2]; for (int i2 = 0; i2 < max_t; i2++) { for (int i3 = 0; i2+i3 < max_t; i3++) { if (rieki[k1][i3]+table[i1][i2] > rieki[k2][i2+i3]) rieki[k2][i2+i3] = rieki[k1][i3]+table[i1][i2]; } } k1++; k1 %= 2; k2++; k2 %= 2; } // 結果の出力 int max = -1; for (int i1 = 0; i1 < max_t ; i1++) { if (rieki[k1][i1] > max) max = rieki[k1][i1]; } System.out.printf("最大利益(最大効用) %d\n", max); } }
N W w1 v1 // 1 番目の品物の重さとそれを入れた場合の効用 w2 v2 // 2 番目の品物の重さとそれを入れた場合の効用 ・・・ wN vN
4 6 1 2 3 5 3 4 3 3
/***************************************/ /* 動的計画法(0-1ナップザック問題) */ /* ー品物毎のデータを出力したい場合ー */ /* coded by Y.Suganuma */ /***************************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) throws IOException { // データの入力と領域の確保 Scanner sc = new Scanner(System.in); int N = sc.nextInt(); // 品物の数 int W = sc.nextInt(); // 重さの上限 int w[] = new int [N]; // 各品物の重さ int v[] = new int [N]; // 各品物の効用 for (int i1 = 0; i1 < N; i1++) { w[i1] = sc.nextInt(); v[i1] = sc.nextInt(); } // 動的計画法 // 初期設定(1段目) int prev[][] = new int [N][W+1]; // 前段までの品物の重さ int dp[][] = new int [N][W+1]; // ナップザック内の品物の重さ for (int i1 = 0; i1 <= W; i1++) dp[0][i1] = -1; if (w[0] <= W) dp[0][w[0]] = v[0]; for (int i1 = 0; i1 <= W; i1++) prev[0][i1] = -1; // 2段目以降 for (int i1 = 1; i1 < N; i1++) { for (int wt = 0; wt <= W; wt++) { dp[i1][wt] = dp[i1-1][wt]; prev[i1][wt] = prev[i1-1][wt]; } // 最初の品物である場合 if (w[i1] <= W && dp[i1][w[i1]] < v[i1]) { dp[i1][w[i1]] = v[i1]; prev[i1][w[i1]] = 0; } // 過去に品物が入っている場合 for (int wt = 1; wt <= W; wt++) { if (dp[i1-1][wt] > 0 && wt+w[i1] <= W) { if (dp[i1-1][wt]+v[i1] > dp[i1][wt+w[i1]]) { dp[i1][wt+w[i1]] = dp[i1-1][wt] + v[i1]; prev[i1][wt+w[i1]] = wt; } } } } // 結果の出力 int k = -1, ans = -1; for (int i1 = 0; i1 <= W; i1++) { if (dp[N-1][i1] > ans) { ans = dp[N-1][i1]; k = i1; } } System.out.printf("最大効用 %d\n", ans); for (int i1 = N-1; i1 > 0; i1--) { int k1 = 0; if (dp[i1][k] != dp[i1-1][k]) { k1 = k - prev[i1][k]; k = prev[i1][k]; } int vv = (k1 <= 0) ? 0 : v[i1]; System.out.printf(" 品物 %d 重さ %d 効用 %d\n", i1+1, k1, vv); } int vv = (k <= 0) ? 0 : v[0]; System.out.printf(" 品物 1 重さ %d 効用 %d\n", k, vv); } }
/*****************************************/ /* 動的計画法(0-1ナップザック問題) */ /* ー品物毎のデータを必要としない場合ー */ /* coded by Y.Suganuma */ /*****************************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) throws IOException { // データの入力と領域の確保 Scanner sc = new Scanner(System.in); int N = sc.nextInt(); // 品物の数 int W = sc.nextInt(); // 重さの上限 int w[] = new int [N]; // 各品物の重さ int v[] = new int [N]; // 各品物の効用 for (int i1 = 0; i1 < N; i1++) { w[i1] = sc.nextInt(); v[i1] = sc.nextInt(); } // 動的計画法 // 初期設定(1段目) int dp[][] = new int [2][W+1]; // ナップザック内の品物の重さ for (int i1 = 0; i1 <= W; i1++) dp[0][i1] = -1; if (w[0] <= W) dp[0][w[0]] = v[0]; int k1 = 0, k2 = 1; // 2段目以降 for (int i1 = 1; i1 < N; i1++) { for (int wt = 0; wt <= W; wt++) dp[k2][wt] = dp[k1][wt]; // 最初の品物である場合 if (w[i1] <= W && dp[k2][w[i1]] < v[i1]) dp[k2][w[i1]] = v[i1]; // 過去に品物が入っている場合 for (int wt = 1; wt <= W; wt++) { if (dp[k1][wt] > 0 && wt+w[i1] <= W) { if (dp[k1][wt]+v[i1] > dp[k2][wt+w[i1]]) dp[k2][wt+w[i1]] = dp[k1][wt] + v[i1]; } } k1++; k1 %= 2; k2++; k2 %= 2; } // 結果の出力 int ans = 0; for (int i1 = 0; i1 <= W; i1++) { if (dp[k1][i1] > ans) ans = dp[k1][i1]; } System.out.printf("最大効用 %d\n", ans); } }
N M // ノードの数,接続データの数(接続データが無いノード間は移動できない) ni nj rij // ノード ni と ノード nj 間の距離は rij ・・・
7 10 0 1 2 0 2 5 1 2 4 1 3 6 1 4 10 2 3 2 3 5 1 4 5 3 4 6 5 5 6 9
/*******************************************/ /* 動的計画法(グラフにおける最短距離問題)*/ /* ー経路を出力したい場合ー */ /* coded by Y.Suganuma */ /*******************************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) throws IOException { // データの入力と領域の確保 Scanner sc = new Scanner(System.in); int N = sc.nextInt(); // ノードの数 int M = sc.nextInt(); // 接続状況データ数 int r[][] = new int [N][N]; // ノード間の距離 for (int i1 = 0; i1 < N; i1++) { for (int i2 = 0; i2 < N; i2++) r[i1][i2] = 0; } for (int i1 = 0; i1 < M; i1++) { int k1 = sc.nextInt(); int k2 = sc.nextInt(); r[k1][k2] = sc.nextInt(); } for (int i1 = 0; i1 < N-1; i1++) { for (int i2 = i1+1; i2 < N; i2++) r[i2][i1] = r[i1][i2]; } // 動的計画法 // 初期設定(1段目) int prev[][] = new int [N][N]; // 前のノード int dp[][] = new int [N][N]; // ノードへ達するまでの距離 for (int i1 = 0; i1 < N; i1++) { for (int i2 = 0; i2 < N; i2++) { prev[i1][i2] = -1; dp[i1][i2] = -1; } } dp[0][0] = 0; // 2段目以降 int n = 0, sw = 1; while(sw > 0) { sw = 0; for (int i1 = 0; i1 < N; i1++) { dp[n+1][i1] = dp[n][i1]; prev[n+1][i1] = prev[n][i1]; } for (int i1 = 0; i1 < N; i1++) { for (int i2 = 0; i2 < N; i2++) { if (dp[n][i1] >= 0 && r[i1][i2] > 0) { if (dp[n+1][i2] < 0 || (dp[n][i1]+r[i1][i2] < dp[n+1][i2])) { dp[n+1][i2] = dp[n][i1] + r[i1][i2]; prev[n+1][i2] = i1; sw = 1; } } } } if (sw > 0) n++; } // 結果の出力 System.out.printf("最短距離 %d\n", dp[n][N-1]); int k = N - 1; System.out.printf(" ノード番号 %d\n", k); while (n > 0) { System.out.printf(" ノード番号 %d\n", prev[n][k]); k = prev[n][k]; n--; } } }
/*******************************************/ /* 動的計画法(グラフにおける最短距離問題)*/ /* ー経路を出力する必要が無い場合ー */ /* coded by Y.Suganuma */ /*******************************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) throws IOException { // データの入力と領域の確保 Scanner sc = new Scanner(System.in); int N = sc.nextInt(); // ノードの数 int M = sc.nextInt(); // 接続状況データ数 int r[][] = new int [N][N]; // ノード間の距離 for (int i1 = 0; i1 < N; i1++) { for (int i2 = 0; i2 < N; i2++) r[i1][i2] = 0; } for (int i1 = 0; i1 < M; i1++) { int k1 = sc.nextInt(); int k2 = sc.nextInt(); r[k1][k2] = sc.nextInt(); } for (int i1 = 0; i1 < N-1; i1++) { for (int i2 = i1+1; i2 < N; i2++) r[i2][i1] = r[i1][i2]; } // 動的計画法 // 初期設定(1段目) int dp[][] = new int [2][N]; // ノードへ達するまでの距離 for (int i1 = 0; i1 < 2; i1++) { for (int i2 = 0; i2 < N; i2++) dp[i1][i2] = -1; } dp[0][0] = 0; // 2段目以降 int sw = 1, k1 = 0, k2 = 1; while(sw > 0) { sw = 0; for (int i1 = 0; i1 < N; i1++) dp[k2][i1] = dp[k1][i1]; for (int i1 = 0; i1 < N; i1++) { for (int i2 = 0; i2 < N; i2++) { if (dp[k1][i1] >= 0 && r[i1][i2] > 0) { if (dp[k2][i2] < 0 || (dp[k1][i1]+r[i1][i2] < dp[k2][i2])) { dp[k2][i2] = dp[k1][i1] + r[i1][i2]; sw = 1; } } } } if (sw > 0) { k1++; k1 %= 2; k2++; k2 %= 2; } } // 結果の出力 System.out.printf("最短距離 %d\n", dp[k1][N-1]); } }