更新第一题
This commit is contained in:
parent
ad465c2b7d
commit
8f85e5eec8
|
@ -0,0 +1,5 @@
|
|||
*.exe
|
||||
.vscode/*
|
||||
template/*
|
||||
*.zip
|
||||
*/datas/*
|
|
@ -0,0 +1,5 @@
|
|||
1 4 3 2
|
||||
1 4 5
|
||||
8 2
|
||||
3 5 2
|
||||
4
|
|
@ -0,0 +1,37 @@
|
|||
from cyaron import * # 引入CYaRon的库
|
||||
|
||||
T = 1000
|
||||
n = 100
|
||||
w = []
|
||||
|
||||
|
||||
for i in range(10):
|
||||
test_data = IO(file_prefix="./datas/t1_", data_id=i+1)
|
||||
T = 10
|
||||
n = randint(1, 10)
|
||||
w = [randint(1, 4) for i in range(n)]
|
||||
test_data.input_writeln(T)
|
||||
test_data.input_writeln(n)
|
||||
test_data.input_writeln(w)
|
||||
test_data.output_gen("solution1.exe")
|
||||
|
||||
for i in range(10):
|
||||
test_data = IO(file_prefix="./datas/t1_", data_id=i+11)
|
||||
T = 30
|
||||
n = randint(6, 10)
|
||||
w = [randint(1, 10) for i in range(n)]
|
||||
test_data.input_writeln(T)
|
||||
test_data.input_writeln(n)
|
||||
test_data.input_writeln(w)
|
||||
test_data.output_gen("solution1.exe")
|
||||
|
||||
|
||||
for i in range(10):
|
||||
test_data = IO(file_prefix="./datas/t1_", data_id=i+21)
|
||||
T = 50
|
||||
n = randint(15, 35)
|
||||
w = [randint(1, 4) for i in range(n)]
|
||||
test_data.input_writeln(T)
|
||||
test_data.input_writeln(n)
|
||||
test_data.input_writeln(w)
|
||||
test_data.output_gen("solution1.exe")
|
|
@ -0,0 +1,15 @@
|
|||
## 问题描述
|
||||
假设有一个能装入总体积为`T`的背包和`n`件体积分别为`w1,w2,…wn`的物品,能否从`n`件物品中挑选若干件恰好装背包,即使`w1+w2+…+wm=T`,要求找出所有满足上述条件的解。
|
||||
例如:当`T=10`,各件物品的体积`{1,8,4,3,5,2}`时,可找到下列`4`组解:
|
||||
- `(1,4,3,2)`
|
||||
- `(1,4,5)`
|
||||
- `(8,2)`
|
||||
- `(3,5,2)`
|
||||
|
||||
## 实现提示
|
||||
可利用回溯法的设计思想来解决背包问题。首先,将物品排成一列,然后,顺序选取物品装入背包,若已选取`i`件物品后未满,则继续选取第`i+1`件,若该件物品“太大”不能装入,则弃之,继续选取下一件,直至背包装满为。
|
||||
|
||||
如果在剩余的物品中找不到合适的物品以填满背包,则说明“刚刚”装入的物品“不合适”,应将它取出“弃之一”,继续再从“它之后”的物品中选取,如此重复,直到求得满足条件的解,或者无解。
|
||||
|
||||
由于回溯求解的规则是“后进先出”,自然要用到“栈”。
|
||||
进一步考虑:如果每件物品都有体积和价值,背包又有大小限制,求解背包中存放物品总价值最大的问题解---最优解或近似最优解。
|
|
@ -0,0 +1,48 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define MAX_N 100
|
||||
|
||||
int T;
|
||||
int n;
|
||||
int w[MAX_N];
|
||||
int x[MAX_N];
|
||||
int solution_count = 0;
|
||||
|
||||
// 暴力搜索,每个物品都有选和不选两种情况
|
||||
void d(int t, int sum, int k) {
|
||||
if (sum == T) {
|
||||
solution_count++;
|
||||
if (solution_count > 50)
|
||||
return;
|
||||
int *re = malloc(sizeof(int) * k);
|
||||
int j = 0;
|
||||
for (int i = 0; i < k; i++) {
|
||||
if (x[i]) {
|
||||
re[j++] = w[i];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < j; i++) {
|
||||
printf("%d ", re[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else if (sum < T && k < n) {
|
||||
x[k] = 1;
|
||||
d(t + 1, sum + w[k], k + 1);
|
||||
x[k] = 0;
|
||||
d(t + 1, sum, k + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// freopen("data.in", "r", stdin);
|
||||
// freopen("data.out", "w", stdout);
|
||||
scanf("%d", &T);
|
||||
scanf("%d", &n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
scanf("%d", &w[i]);
|
||||
}
|
||||
d(0, 0, 0);
|
||||
printf("%d", solution_count);
|
||||
// printf("Total Solution Count: %d\n", solution_count);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
## 思路
|
||||
一个能装入总体积为`T`的背包和`n`件体积分别为`w1,w2,…wn`的物品,能否从`n`件物品中挑选若干件恰好装背包,即使`w1+w2+…+wm=T`
|
||||
|
||||
相当于取一个向量 $n$ = $(x_1, x_2, ..., x_n)$,其中 $x_i \in \{0, 1\}$,使得 $\sum_{i=1}^n x_i w_i = T$,求所有满足条件的 $n$。
|
||||
|
||||
使用暴力 `dfs` 搜索,搜索每一件物品的选择情况,符合条件时输出。
|
||||
|
||||
总情况数为 $2^n$,时间复杂度为 $O(2^n)$。
|
||||
|
||||
## 代码及解释
|
|
@ -0,0 +1,46 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define MAX_N 100
|
||||
|
||||
int T;
|
||||
int n;
|
||||
int w[MAX_N];
|
||||
int x[MAX_N];
|
||||
int solution_count = 0;
|
||||
|
||||
void dfs(int t, int sum, int k) {
|
||||
if (sum == T) {
|
||||
solution_count++;
|
||||
int *re = malloc(sizeof(int) * k);
|
||||
int j = 0;
|
||||
for (int i = 0; i < k; i++) {
|
||||
if (x[i]) {
|
||||
re[j++] = w[i];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < j; i++) {
|
||||
printf("%d ", re[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else if (sum < T && k < n) {
|
||||
if (sum + w[k] <= T) {
|
||||
x[k] = 1;
|
||||
dfs(t + 1, sum + w[k], k + 1);
|
||||
}
|
||||
x[k] = 0;
|
||||
dfs(t + 1, sum, k + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
freopen("data.in", "r", stdin);
|
||||
freopen("data.out", "w", stdout);
|
||||
scanf("%d", &T);
|
||||
scanf("%d", &n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
scanf("%d", &w[i]);
|
||||
}
|
||||
dfs(0, 0, 0);
|
||||
printf("Total Solution Count: %d\n", solution_count);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
## 思路
|
||||
使用 `dfs`,搜索每一件物品的选择情况,符合条件时输出。
|
||||
|
||||
使用 `sum+w[k]<=T` 进行剪枝,提高运行速度
|
||||
|
||||
## 代码及解释
|
|
@ -0,0 +1,107 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define MAX_N 100
|
||||
|
||||
int T;
|
||||
int n;
|
||||
int w[MAX_N];
|
||||
int index_arr[MAX_N];
|
||||
int solution_count = 0;
|
||||
|
||||
void printSubset(int *subset, int size) {
|
||||
solution_count++;
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("%d", subset[i]);
|
||||
if (i != size - 1) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void findSubsets(int *arr, int n, int T, int *subset, int size, int index) {
|
||||
if (T == 0) {
|
||||
printSubset(subset, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (index == n) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (arr[index] > T) {
|
||||
return;
|
||||
}
|
||||
|
||||
subset[size] = arr[index];
|
||||
findSubsets(arr, n, T - arr[index], subset, size + 1, index + 1);
|
||||
|
||||
while (index < n - 1 && arr[index] == arr[index + 1]) {
|
||||
index++;
|
||||
}
|
||||
findSubsets(arr, n, T, subset, size, index + 1);
|
||||
}
|
||||
|
||||
void d(int *arr, int n, int T) {
|
||||
int *subset = (int *)malloc(n * sizeof(int));
|
||||
|
||||
int size = 0;
|
||||
findSubsets(arr, n, T, subset, size, 0);
|
||||
|
||||
free(subset);
|
||||
}
|
||||
|
||||
void swap(int *arr, int i, int j) {
|
||||
int tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = tmp;
|
||||
|
||||
tmp = index_arr[i];
|
||||
index_arr[i] = index_arr[j];
|
||||
index_arr[j] = tmp;
|
||||
}
|
||||
|
||||
void sort(int *arr, int n) {
|
||||
int i = 0, j = n - 1;
|
||||
int pivot = arr[0];
|
||||
int pivot_index = 0;
|
||||
while (i < j) {
|
||||
while (i < j && arr[j] >= pivot) {
|
||||
j--;
|
||||
}
|
||||
if (i < j) {
|
||||
swap(arr, i, j);
|
||||
i++;
|
||||
}
|
||||
while (i < j && arr[i] <= pivot) {
|
||||
i++;
|
||||
}
|
||||
if (i < j) {
|
||||
swap(arr, i, j);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
freopen("data.in", "r", stdin);
|
||||
// freopen("data.out", "w", stdout);
|
||||
scanf("%d", &T);
|
||||
scanf("%d", &n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
scanf("%d", &w[i]);
|
||||
index_arr[i] = i;
|
||||
}
|
||||
|
||||
sort(w, n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
printf("%d ", w[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
||||
d(w, n, T);
|
||||
// printf("Total Solution Count: %d\n", solution_count);
|
||||
printf("%d", solution_count);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue