11. 假设有7个物品,它们的重量和价值如下表所示。若这些物品均不能被分割,且背包容量M=150,设计算法求解怎么装才能使得获取的价值最大?请写出伪代码。
#include <stdio.h>
#define MAX_ITEMS 100
#define MAX_WEIGHT 1000
int max(int a, int b) {
return (a > b) ? a : b;
}
// 动态规划求解背包问题
void knapsack(int n, int capacity, int weights[], int values[]) {
int dp[MAX_ITEMS + 1][MAX_WEIGHT + 1] = {0};
int i, w;
// 填表格
for (i = 1; i <= n; i++) {
for (w = 1; w <= capacity; w++) {
if (weights[i - 1] > w) {
dp[i][w] = dp[i - 1][w];
} else {
dp[i][w] = max(dp[i - 1][w], values[i - 1] + dp[i - 1][w - weights[i - 1]]);
}
}
}
// 回溯找出装入背包的物品
int res[MAX_ITEMS];
int k = n, c = capacity;
int num = 0;
while (k > 0 && c > 0) {
if (dp[k][c] != dp[k - 1][c]) {
res[num++] = k;
c -= weights[k - 1];
}
k--;
}
// 输出结果
for (i = num - 1; i >= 0; i--) {
printf("%-d ", res[i]);
}
printf("\n");
printf("end");
}
int main() {
int n, capacity;
scanf("%d %d", &n, &capacity);
int weights[MAX_ITEMS], values[MAX_ITEMS];
for (int i = 0; i < n; i++) {
scanf("%d", &weights[i]);
}
for (int i = 0; i < n; i++) {
scanf("%d", &values[i]);
}
// 调用背包问题求解函数
knapsack(n, capacity, weights, values);
return 0;
}
运行结果:
12. 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 或 3 个台阶。你有多少种不同的方法可以爬到楼顶呢?请用动态规划算法解决并写出伪代码。(n需要在算法中输入)
#include <stdio.h>
int climbStairs(int n)
{
int dp[n];
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++)
{
dp[i] = dp[i-1] + dp[i-2]+dp[i-3];
}
return dp[n];
}
int main()
{
int n ;
scanf("%d",&n);
int result = climbStairs(n);
printf("%d\n", result); // 输出结果
return 0;
}
运行结果:
13.最长公共子序列是指两个序列共同拥有的最长的子序列,这个子序列在两个序列中的位置不必连续,但必须保持原有的顺序。例如,对于序列X=“ABCBDAB”和序列Y=“BDCABA”,它们的最长公共子序列为“BCBA”,长度为4。编程输入两个字符串,求其最长公共子序列的长度。
#include <stdio.h>
#include <string.h>
// 函数声明
int longestCommonSubsequence(char *X, char *Y);
int main() {
char X[100], Y[100];
// 输入两个字符串
printf("Enter the first string: ");
scanf("%99s", X); // 使用%99s限制输入长度,避免溢出
printf("Enter the second string: ");
scanf("%99s", Y);
// 调用函数计算LCS长度
int length = longestCommonSubsequence(X, Y);
// 输出LCS长度
printf("The length of the Longest Common Subsequence is: %d\n", length);
return 0;
}
// 函数定义:计算两个字符串的最长公共子序列的长度
int longestCommonSubsequence(char *X, char *Y) {
int m = strlen(X);
int n = strlen(Y);
// 创建一个二维数组dp,用于存储子问题的解
int dp[m + 1][n + 1];
// 初始化dp数组
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
}
}
}
// 填充dp数组
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (X[i - 1] == Y[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = (dp[i - 1][j] > dp[i][j - 1]) ? dp[i - 1][j] : dp[i][j - 1];
}
}
}
// dp[m][n]存储了X和Y的最长公共子序列的长度
return dp[m][n];
}
运行结果:
14. 填入0~9的数字。要求:连续的两个数字不能相邻。(左右.上下.对角都算相邻) 一共有多少种可能的填数方案? 请输出一个表示方案数目的整数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int disp(int a[], int n) {
int i;
for (i = 0; i < 9; i++) {
if (abs(a[i] - a[i + 1]) == 1 && i != 2 && i != 6)
return 0;
}
for (i = 0; i < 6; i++) {
if (abs(a[i] - a[i + 4]) == 1)
return 0;
}
for (i = 0; i < 7; i++) {
if (abs(a[i] - a[i + 3]) == 1 && i != 3)
return 0;
}
for (i = 0; i < 5; i++) {
if (abs(a[i] - a[i + 5]) == 1 && i != 2)
return 0;
}
return 1;
}
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
void permute(int *a, int l, int r, int *count) {
int i;
if (l == r) {
if (disp(a, r + 1)) {
(*count)++;
}
} else {
for (i = l; i <= r; i++) {
swap((a + l), (a + i));
permute(a, l + 1, r, count);
swap((a + l), (a + i)); // backtrack
}
}
}
int main() {
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int n = 10;
int count = 0;
permute(a, 0, n - 1, &count);
printf("%d\n", count);
return 0;
}
运行结果:
15. 编程输出一个特别的数,该数是一个由1~9组成的9位数,每个数字只能出现一次,且这个9位数由高位到低位前i位能被i整除。
#include <stdio.h>
int main(void)
{
long i[9];
long j, n;
i[4] = 5;
for (i[0] = 1; i[0] < 10; i[0] += 2)
{
for (i[1] = 2; i[1] < 9; i[1] += 2)
{
for (i[2] = 1; i[2] < 10; i[2] += 2)
{
if (i[2] == i[0])
continue;
for (i[3] = 2; i[3] < 9; i[3] += 2)
{
if (i[3] == i[1])
continue;
for (i[5] = 2; i[5] < 9; i[5] += 2)
{
if (i[5] == i[3] || i[5] == i[1])
continue;
for (i[6] = 1; i[6] < 10; i[6] += 2)
{
if (i[6] == i[4] || i[6] == i[2] || i[6] == i[0])
continue;
for (i[7] = 2; i[7] < 9; i[7] += 2)
{
if (i[7] == i[5] || i[7] == i[3] || i[7] == i[1])
continue;
for (i[8] = 1; i[8] < 10; i[8] += 2)
{
if (i[8] == i[6] || i[8] == i[4] || i[8] == i[2] || i[8] == i[0])
continue;
n = 0;
for (j = 0; j < 9; j++)
{
n = n * 10 + i[j];
if (n % (j + 1) != 0)
break;
}
if (j == 9)
printf("%ld\n", n);
}
}
}
}
}
}
}
}
}
运行结果:
结语
不举步,越不过栅栏
不迈腿,登不上高山
!!!