算法设计与分析重要代码(含注释)

1.数塔问题

#include <stdio.h>
#define MAX_ROW 50 //定义最大的行数为50

int main(){
    int a[MAX_ROW][MAX_ROW][3], i, j, n; //定义一个三维数组a,以及三个循环变量i,j,n
    printf("Please input the number of rows: "); //输出提示语句,要求用户输入行数
    scanf("%d", &n); //从键盘输入行数

    //输入数据并初始化
    for(i=1; i<=n; i++){ //外层循环控制行数
        for(j=1; j<=i; j++){ //内层循环控制列数
            scanf("%d", &a[i][j][1]); //从键盘输入该位置的值
            a[i][j][2] = a[i][j][1]; //将该位置的值同时赋给第三维数组中的第二个元素,作为该位置的最大和
            a[i][j][3] = 0; //将该位置的最大和路径初始化为0
        }
    }

    //动态规划
    for(i=n-1; i>=1; i--){ //从倒数第二行开始倒序循环到第一行
        for(j=1; j<=i; j++){ //内层循环控制列数
            if(a[i+1][j][2] > a[i+1][j+1][2]){ //如果下一行的左侧位置的最大和大于右侧位置的最大和
                a[i][j][2] += a[i+1][j][2]; //该位置的最大和为该位置的值加上下一行的左侧位置的最大和
                a[i][j][3] = 0; //该位置的最大和路径为左侧
            }
            else{ //否则下一行的右侧位置的最大和大于等于左侧位置的最大和
                a[i][j][2] += a[i+1][j+1][2]; //该位置的最大和为该位置的值加上下一行的右侧位置的最大和
                a[i][j][3] = 1; //该位置的最大和路径为右侧
            }
        }
    }

    //输出最大和以及路径
    printf("Max sum: %d\nPath: ", a[1][1][2]); //输出最大和
    j = 1; //从第一列开始
    for(i=1; i<=n-1; i++){ //从第一行开始循环到倒数第二行
        printf("%d->", a[i][j][1]); //输出该位置的值
        j += a[i][j][3]; //根据该位置的最大和路径,更新列数
    }
    printf("%d\n", a[n][j][1]); //输出最后一个位置的值

    return 0; //程序结束
}

2.花生收获问题

// 导入标准输入输出库
#include <stdio.h>

// 主函数开始
int main()
{
    int T; // 存储测试数据组数
    scanf("%d", &T); // 读取测试数据组数
    // 循环处理每一组测试数据
    while(T--)
    {
        int R, C; // 存储花生苗的行列数
        scanf("%d%d", &R, &C); // 读取花生苗的行列数
        int a[R][C]; // 存储花生数目
        // 读取每个格子的花生数目
        for(int i=0; i<R; i++)
            for(int j=0; j<C; j++)
                scanf("%d", &a[i][j]);
        // 动态规划求解
        // 处理第一列
        for(int i=1; i<R; i++)
            a[i][0] += a[i-1][0];
        // 处理第一行
        for(int j=1; j<C; j++)
            a[0][j] += a[0][j-1];
        // 处理其余部分
        for(int i=1; i<R; i++)
            for(int j=1; j<C; j++)
                a[i][j] += (a[i-1][j] > a[i][j-1]) ? a[i-1][j] : a[i][j-1];
        // 输出最大花生数目
        printf("%d\n", a[R-1][C-1]);
    }
    return 0; // 程序结束
}

3.贪心算法背包问题(可以选择物品一部分)

#include <stdio.h>
#define MAX_N 1000

int n; // 物品的数量
int W; // 背包的最大负重
int w[MAX_N+1]; // 物品的重量
int v[MAX_N+1]; // 物品的价值
double unit[MAX_N+1]; // 物品的单位价值
double x[MAX_N+1]; // 物品的装入比例

void knapsack()
{
    int i, j;
    double max_unit_v, max_x;
    int index; // 单位价值最大的物品的下标

    // 计算每个物品的单位价值
    for(i=1; i<=n; i++)
        unit[i] = (double)v[i] / w[i];

    // 初始化x数组为0
    for(i=1; i<=n; i++)
        x[i] = 0.0;

    // 重复选择最具有单位价值的物品,并将其装入背包中
    for(i=1; i<=n; i++)
    {
        // 寻找单位价值最大的物品
        max_unit_v = 0.0;
        index = 0;
        for(j=1; j<=n; j++)
        {
            if(x[j] == 0.0 && unit[j] > max_unit_v)
            {
                max_unit_v = unit[j];
                index = j;
            }
        }

        // 计算当前物品可以装入的比例
        if(index != 0)
        {
            if(w[index] <= W)
            {
                x[index] = 1.0;
                W -= w[index];
            }
            else
            {
                max_x = (double)W / w[index];
                x[index] = max_x;
                W = 0;
            }
        }
        else
            break; // 所有物品都已经装入背包中
    }
}

int main()
{
    int i;

    // 读入输入数据
    scanf("%d %d", &n, &W);
    for(i=1; i<=n; i++)
        scanf("%d %d", &w[i], &v[i]);
  
    // 解决背包问题
    knapsack();

    // 输出结果
    double max_v = 0.0;
    for(i=1; i<=n; i++)
        max_v += v[i] * x[i];
    printf("%.2lf\n", max_v);

    return 0;
}

4.活动选择问题

c语言实现

#include<stdio.h>
#include<stdlib.h>

//活动结构体
typedef struct activity{
    int s; //开始时间
    int f; //结束时间
}Activity;

//比较函数
int cmp(const void *a, const void *b){
    return ((Activity*)a)->f - ((Activity*)b)->f;
}

//贪心算法
void TaskSelect(Activity act[], int n){
    int i, j;
    printf("安排的活动为:");
    printf("(%d,%d)", act[0].s, act[0].f); //先选择第一个活动
    j=0; //记录当前最后一个被选中的活动
    for(i=1; i<n; i++){
        if(act[i].s >= act[j].f){ //如果与当前最后一个被选中的活动兼容
            printf(",(%d,%d)", act[i].s, act[i].f); //选择该活动
            j=i; //更新最后一个被选中的活动
        }
    }
}

int main(){
    int n, i;
    Activity *act;

    //读入活动数量
    printf("请输入活动的数量:");
    scanf("%d", &n);

    //动态分配内存
    act = (Activity*)malloc(n * sizeof(Activity));

    //读入活动的起始时间
    printf("请输入每个活动的起始时间:");
    for(i=0; i<n; i++){
        scanf("%d", &act[i].s);
    }

    //读入活动的完成时间
    printf("请输入每个活动的完成时间:");
    for(i=0; i<n; i++){
        scanf("%d", &act[i].f);
    }

    //按完成时间对活动进行排序
    qsort(act, n, sizeof(Activity), cmp);

    //贪心算法
    TaskSelect(act, n);

    //释放内存
    free(act);

    return 0;
}

python实现:

n = int(input())
start =eval(input("请输入开始时间例如[1,3,8]:"))
end = eval(input("请输入结束时间例如[1,3,8]:"))

# 构建活动列表
activity_list = []
for i in range(n):
    activity_list.append([start[i], end[i], i+1])

# 按结束时间排序
activity_list.sort(key=lambda x:x[1])

# 贪心选择活动
selected_activities = []
last_end_time = 0
for activity in activity_list:
    if activity[0] >= last_end_time:
        selected_activities.append(activity[2])
        last_end_time = activity[1]

# 输出结果
print("所选择的活动序号分别是:")
print(selected_activities)




5.矩阵连乘问题

第一种:

#include<iostream>
using namespace std;
const int N = 100;
int A[N];//矩阵规模
int m[N][N];//最优解
int s[N][N];
void MatrixChain(int n)
{
	int r, i, j, k;
	for (i = 0; i <= n; i++)//初始化对角线
	{
		m[i][i] = 0;
	}
	for (r = 2; r <= n; r++)//r个矩阵连乘
	{
		for (i = 1; i <= n - r + 1; i++)//r个矩阵的r-1个空隙中依次测试最优点
		{
			j = i + r - 1;
			m[i][j] = m[i][i]+m[i + 1][j] + A[i - 1] * A[i] * A[j];
			s[i][j] = i;
			for (k = i + 1; k < j; k++)//变换分隔位置,逐一测试
			{
				int t = m[i][k] + m[k + 1][j] + A[i - 1] * A[k] * A[j];
				if (t < m[i][j])//如果变换后的位置更优,则替换原来的分隔方法。
				{
					m[i][j] = t;
					s[i][j] = k;
				}
			}
		}
	}
}
void print(int i, int j)
{
	if (i == j)
	{
		cout << "A[" << i << "]";
		return;
	}
	cout << "(";
	print(i, s[i][j]);
	print(s[i][j] + 1, j);//递归1到s[1][j]
	cout << ")";
}
int main()
{
	int n;//n个矩阵
	cout <<"请输入矩阵的个数n:\n";
	cin >> n;
	int i, j;
	cout <<"请输入每个矩阵的行数和最后一个矩阵的列数:\n"; 
	for (i = 0; i <= n; i++)
	{
		cin >> A[i];
	}
	MatrixChain(n);
	cout << "最佳添加括号的方式为:";
	print(1, n);
	cout << "\n最小计算量的值为:" << m[1][n] << endl;
	return 0;
}

第二种:

#include <stdio.h>
#include <limits.h>
#define N 100
int dp[N][N], s[N][N], p[N];
int matrixChain(int n)
{
    int i, j, k, l, q;
    for (i = 1; i <= n; i++) dp[i][i] = 0;
    for (l = 2; l <= n; l++) {
        for (i = 1; i <= n - l + 1; i++) {
            j = i + l - 1;
            dp[i][j] = INT_MAX;
            for (k = i; k < j; k++) {
                q = dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j];
                if (q < dp[i][j]) {
                    dp[i][j] = q;
                    s[i][j] = k;
                }
            }
        }
    }
    return dp[1][n];
}
void printOrder(int i, int j)
{
    if (i == j) {
        printf("A[%d]", i);
    } else {
        printf("(");
        printOrder(i, s[i][j]);
        printOrder(s[i][j]+1, j);
        printf(")");
    }
}
int main()
{
    int n, i;
    printf("请输入矩阵的个数n:\n");
    scanf("%d", &n);
    printf("请依次输入每个矩阵的行数和最后一个矩阵的列数:\n");
    for (i = 0; i <= n; i++) 
		scanf("%d", &p[i]);
    int minCount = matrixChain(n); 
    printOrder(1, n);
    printf("\n最小计算量的值为:%d", minCount);
    return 0;
}

6.最大连续字段和

#include<iostream>
using namespace std;

int maxSum(int a[], int n){
	
	int sum = 0;
	int b = 0;
	
	for(int i = 0; i < n; i++){
		
		if(b > 0){
		  b += a[i];	
		}	
		else
			b = a[i];
		
		if(b > sum)
			sum = b;
	}
	return sum;	
}

int main(){
	int length;
	int a[] = {-2, 11, -4, 13, -5, -2};
	length=sizeof(a)/sizeof(int);

	for(int i= 0; i <length; i++)
	{
		cout<<a[i]<<" ";
	}	 
	cout<<endl;
	cout<<"数组a的最大连续子段和为:" << maxSum(a, length)<<endl;
	return 0;
}

7.最长公共子序列

Peace_joy. 2023/5/6 14:26:05
#include <stdio.h>
#include <string.h>
#define MAXLEN 100 // 宏定义,定义最大字符串长度为100

int max(int a, int b) { // 定义一个返回两个整数中较大值的函数
    return (a > b) ? a : b;
}

void lcs_length(char *X, char *Y, int m, int n, int c[][MAXLEN], int b[][MAXLEN]) { 
    // 定义最长公共子序列的长度及其来源的矩阵,X和Y为输入的两个字符串,m和n分别为它们的长度
    int i, j; // 定义循环变量i和j
    for (i = 0; i <= m; i++) { // 初始化第一列
        c[i][0] = 0; // 第一列都为0
    }
    for (j = 0; j <= n; j++) { // 初始化第一行
        c[0][j] = 0; // 第一行都为0
    }
    for (i = 1; i <= m; i++) { // 求解子问题
        for (j = 1; j <= n; j++) {
            if (X[i-1] == Y[j-1]) { // 如果当前字符相同
                c[i][j] = c[i-1][j-1] + 1; // 最长公共子序列长度加1
                b[i][j] = 0; // 标记来源为左上角
            } else if (c[i-1][j] >= c[i][j-1]) { // 如果上面的值大于等于左边的值
                c[i][j] = c[i-1][j]; // 最长公共子序列长度取上面的值
                b[i][j] = 1; // 标记来源为上面
            } else { // 如果上面的值小于左边的值
                c[i][j] = c[i][j-1]; // 最长公共子序列长度取左边的值
                b[i][j] = 2; // 标记来源为左边
            }
        }
    }
}

void print_lcs(int b[][MAXLEN], char *X, int i, int j) { // 输出最长公共子序列的函数
    if (i == 0 || j == 0) { // 如果i或j为0,结束递归
        return;
    }
    if (b[i][j] == 0) { // 如果来源为左上角
        print_lcs(b, X, i-1, j-1); // 递归输出
        printf("%c ", X[i-1]); // 输出当前字符
    } else if (b[i][j] == 1) { // 如果来源为上面
        print_lcs(b, X, i-1, j); // 递归输出
    } else { // 如果来源为左边
        print_lcs(b, X, i, j-1); // 递归输出
    }
}


Peace_joy. 2023/5/6 14:26:16
//定义两个字符串X和Y,以及c和b数组。c数组用来存储LCS的长度,b数组用来帮助构造LCS
int main() {
    char X[MAXLEN], Y[MAXLEN];
    int c[MAXLEN][MAXLEN], b[MAXLEN][MAXLEN];
    int m, n, i, j;
    //从用户处输入字符串X和Y
    printf("Enter the first string: ");
    scanf("%s", X);
    printf("Enter the second string: ");
    scanf("%s", Y);
    //计算字符串X和Y的长度
    m = strlen(X);
    n = strlen(Y);
    //调用lcs_length函数计算LCS的长度,并将结果存储在c和b数组中
    lcs_length(X, Y, m, n, c, b);
    //输出LCS的长度
    printf("The length of the longest common subsequence is %d\n", c[m][n]);
    //调用print_lcs函数构造LCS,并输出
    printf("The longest common subsequence is: ");
    print_lcs(b, X, m, n);
    return 0;
}

8.0-1背包问题

C语言代码实现



#include<stdio.h>
#define MAX_N 100
int max(int a,int b){
    return a>b?a:b;  //返回较大值
}
int main(){
    int n,m;
    int w[MAX_N],v[MAX_N];  //定义物品重量和价值数组
    int dp[MAX_N][MAX_N]={0};  //定义dp数组,初始化为0
    printf("请输入物品数量和背包容量:\n");
    scanf("%d%d",&n,&m);
    printf("请输入每个物品的重量和价值:\n");
    for(int i=1;i<=n;i++){
        scanf("%d%d",&w[i],&v[i]);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(j<w[i]){  //若当前物品的重量大于背包容量,无法装入
                dp[i][j]=dp[i-1][j];
            }
            else{  //当前物品可以装入背包
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);  //取最大值
            }
        }
    }
    printf("最大价值为:%d\n",dp[n][m]);  //输出最大价值
    return 0;
}

python代码实现:



def max(a,b):
    return a if a>b else b  #返回较大值
n,m=map(int,input("请输入物品数量和背包容量:").split())
w=[0]*MAX_N  #定义物品重量数组
v=[0]*MAX_N  #定义物品价值数组
dp=[[0]*MAX_N for i in range(MAX_N)]  #定义dp数组,初始化为0
print("请输入每个物品的重量和价值:")
for i in range(1,n+1):
    w[i],v[i]=map(int,input().split())
for i in range(1,n+1):
    for j in range(1,m+1):
        if j<w[i]:  #若当前物品的重量大于背包容量,无法装入
            dp[i][j]=dp[i-1][j]
        else:  #当前物品可以装入背包
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])  #取最大值
print("最大价值为:",dp[n][m])  #输出最大价值

10.棋盘覆盖问题

c语言代码实现

#include<stdio.h>
#include<stdlib.h>

#define N 1024

int board[N][N];
int tile_id = 1;

int L = 0;
int T = 0;

void print_board(int size)
{
    int i, j;
    for(i=0; i<size; i++){
        for(j=0; j<size; j++){
            printf("%-3d ", board[i][j]);
        }
        printf("\n");
    }
}

void cover(int tr, int tc, int dr, int dc, int size)
{
    if(size == 1) return;   // 递归终止条件

    int t = tile_id++;
    int s = size / 2;     // 先计算出子棋盘规模

    // 分治策略 
    if(dr < tr+s && dc < tc+s){  //左上角的格子被覆盖
        cover(tr, tc, dr, dc, s);
    }
    else{
        board[tr+s-1][tc+s-1] = t;
        cover(tr, tc, tr+s-1, tc+s-1, s);
    }

    if(dr < tr+s && dc >= tc+s){  // 右上角的格子被覆盖
        cover(tr, tc+s, dr, dc, s);
    }
    else{
        board[tr+s-1][tc+s] = t;
        cover(tr, tc+s, tr+s-1, tc+s, s);
    }

    if(dr >= tr+s && dc < tc+s){  // 左下角的格子被覆盖
        cover(tr+s, tc, dr, dc, s);
    }
    else{
        board[tr+s][tc+s-1] = t;
        cover(tr+s, tc, tr+s, tc+s-1, s);
    }

    if(dr >= tr+s && dc >= tc+s){    // 右下角的格子被覆盖
        cover(tr+s, tc+s, dr, dc, s);
    }
    else{
        board[tr+s][tc+s] = t;
        cover(tr+s, tc+s, tr+s, tc+s, s);
    }
}

int main()
{
    int size;
    printf("请输入棋盘的规模:");
    scanf("%d", &size);

    // 将棋盘全部置为0
    int i, j;
    for(i=0; i<size; i++){
        for(j=0; j<size; j++){
            board[i][j] = 0;
        }
    }

    // 设置特殊起始格子
    int dr, dc;
    printf("请输入特殊起始格子的行坐标和列坐标:");
    scanf("%d %d", &dr, &dc);
    board[dr][dc] = -1;

    cover(0, 0, dr, dc, size);

    // 打印出结果
    print_board(size);

    return 0;
}

python代码实现:

N = 1024

board = [[0]*N for i in range(N)]
tile_id = 1

L = 0
T = 0

def print_board(size):
    for i in range(size):
        for j in range(size):
            print('{:<3d}'.format(board[i][j]), end=' ')
        print()

def cover(tr, tc, dr, dc, size):
    global tile_id

    if size == 1: return

    t = tile_id
    tile_id += 1
    s = size // 2

    if dr < tr+s and dc < tc+s:    # 左上角被覆盖
        cover(tr, tc, dr, dc, s)
    else:
        board[tr+s-1][tc+s-1] = t
        cover(tr, tc, tr+s-1, tc+s-1, s)

    if dr < tr+s and dc >= tc+s:    # 右上角被覆盖
        cover(tr, tc+s, dr, dc, s)
    else:
        board[tr+s-1][tc+s] = t
        cover(tr, tc+s, tr+s-1, tc+s, s)

    if dr >= tr+s and dc < tc+s:    # 左下角被覆盖
        cover(tr+s, tc, dr, dc, s)
    else:
        board[tr+s][tc+s-1] = t
        cover(tr+s, tc, tr+s, tc+s-1, s)

    if dr >= tr+s and dc >= tc+s:    # 右下角被覆盖
        cover(tr+s, tc+s, dr, dc, s)
    else:
        board[tr+s][tc+s] = t
        cover(tr+s, tc+s, tr+s, tc+s, s)

if __name__ == '__main__':
    size = int(input('请输入棋盘的规模:'))

    for i in range(size):
        for j in range(size):
            board[i][j] = 0

    dr, dc = map(int, input('请输入特殊起始格子的行坐标和列坐标:').split())
    board[dr][dc] = -1

    cover(0, 0, dr, dc, size)

    print_board(size)

11.n后问题 

 n后问题是一道经典的算法题目,其要求为在一个n * n的棋盘上放置n个皇后,满足皇后之间不会互相攻击。皇后的攻击规则为在同一行、同一列以及同一对角线上。以下是C语言和Python两种编程语言的实现代码。

C语言实现代码:

#include <stdio.h>
#include <stdlib.h>

#define N 8 // 棋盘大小

int queen[N]; // 存放皇后位置的数组
int count; // 解法计数器

// 判断当前位置是否合法
int is_valid(int row, int col)
{
    int i;
    for (i = 0; i < row; i++)
    {
        // 在同一列或同一对角线上
        if (queen[i] == col || abs(queen[i] - col) == row - i)
        {
            return 0;
        }
    }
    return 1;
}

// 回溯求解皇后位置
void backtrack(int row)
{
    int col;
    if (row == N)
    {
        // 找到一个解法
        count++;
        return;
    }
    for (col = 0; col < N; col++)
    {
        if (is_valid(row, col))
        {
            // 当前位置合法,继续搜索下一行
            queen[row] = col;
            backtrack(row + 1);
        }
    }
}

int main()
{
    int i;
    for (i = 0; i < N; i++)
    {
        queen[i] = -1;
    }
    backtrack(0);
    printf("Total Solutions: %d\n", count);
    return 0;
}

12.算法几大排序

以下是c语言实现的几大排序算法:

1. 冒泡排序

void bubbleSort(int array[], int size) {
    int i, j, temp;
    for (i = 0; i < size - 1; i++) {
        for (j = 0; j < size - 1 - i; j++) {
            if (array[j] > array[j + 1]) {
                temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

2. 选择排序

void selectionSort(int array[], int size) {
    int i, j, temp, minIndex;
    for (i = 0; i < size - 1; i++) {
        minIndex = i;
        for (j = i + 1; j < size; j++) {
            if (array[j] < array[minIndex]) {
                minIndex = j;
            }
        }
        if (minIndex != i) {
            temp = array[i];
            array[i] = array[minIndex];
            array[minIndex] = temp;
        }
    }
}

3. 插入排序

void insertionSort(int array[], int size) {
    int i, j, temp;
    for (i = 1; i < size; i++) {
        temp = array[i];
        j = i - 1;
        while (j >= 0 && array[j] > temp) {
            array[j + 1] = array[j];
            j--;
        }
        array[j + 1] = temp;
    }
}

4. 快速排序

void quickSort(int array[], int left, int right) {
    int i, j, pivot, temp;
    if (left < right) {
        pivot = left;
        i = left;
        j = right;
        while (i < j) {
            while (array[i] <= array[pivot] && i < right) {
                i++;
            }
            while (array[j] > array[pivot]) {
                j--;
            }
            if (i < j) {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
        temp = array[pivot];
        array[pivot] = array[j];
        array[j] = temp;
        quickSort(array, left, j - 1);
        quickSort(array, j + 1, right);
    }
}

5. 归并排序

void merge(int array[], int left, int middle, int right) {
    int i, j, k;
    int n1 = middle - left + 1;
    int n2 = right - middle;
    int L[n1], R[n2];
    for (i = 0; i < n1; i++) {
        L[i] = array[left + i];
    }
    for (j = 0; j < n2; j++) {
        R[j] = array[middle + 1 + j];
    }
    i = 0;
    j = 0;
    k = left;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            array[k] = L[i];
            i++;
        } else {
            array[k] = R[j];
            j++;
        }
        k++;
    }
    while (i < n1) {
        array[k] = L[i];
        i++;
        k++;
    }
    while (j < n2) {
        array[k] = R[j];
        j++;
        k++;
    }
}

void mergeSort(int array[], int left, int right) {
    if (left < right) {
        int middle = left + (right - left) / 2;
        mergeSort(array, left, middle);
        mergeSort(array, middle + 1, right);
        merge(array, left, middle, right);
    }
}

13.猴子吃桃问题

Python实现:

以下是Python语言的程序,用来解决猴子吃桃问题:

```
n = 1
for i in range(9):
    n = (n+1) * 2
print(n)
```

程序的思路是每次反推出前一天的桃子数,直到第一天的桃子数。具体实现中,使用循环语句从后往前推算,最后输出第一天的桃子数。

程序输出:1534

解释:第一天有1534个桃子,猴子每天吃掉一半加一个,第十天最后剩下了一个桃子。

c语言实现:

以下是C语言实现猴子吃桃问题的程序,与Python程序类似:

```
#include <stdio.h>

int main()
{
    int n = 1;
    int i;
    for (i = 0; i < 9; i++) {
        n = (n+1) * 2;
    }
    printf("%d", n);
    return 0;
}
```

程序的思路同上,使用循环语句反推每天的桃子数,最后输出第一天的桃子数。

程序输出:1534

解释同上。

14.图的着色问题

C语言实现:

图的着色问题是指在一个给定的无向图中,用尽量少的颜色将所有节点着色,保证相邻节点颜色不同。这个问题在计算机图形学、计算机网络等领域都有应用。

以下是C语言实现图的着色问题的算法,使用贪心策略:

```
#include <stdio.h>

#define MAX_NODE 100
#define MAX_COLOR 100

int graph[MAX_NODE][MAX_NODE]; // 无向图
int node_num, edge_num; // 节点数、边数
int color[MAX_NODE]; // 节点的颜色
int color_num = 0; // 着色数

int get_min_color(int node) {
    int i, j;
    int color_count[MAX_COLOR] = {0}; // 统计相邻节点的颜色数
    for (i = 0; i < node_num; i++) {
        if (graph[node][i] && color[i]) {
            color_count[color[i]-1]++;
        }
    }
    // 选择颜色数最少的颜色
    int min_count = node_num;
    int min_color;
    for (j = 0; j < color_num; j++) {
        if (color_count[j] < min_count) {
            min_count = color_count[j];
            min_color = j+1;
        }
    }
    return min_color;
}

void color_graph() {
    int i, j;
    for (i = 0; i < node_num; i++) {
        color[i] = 0;
    }
    color_num = 0;
    // 对每个节点进行着色
    for (i = 0; i < node_num; i++) {
        if (color[i] == 0) {
            color[i] = get_min_color(i);
            if (color[i] > color_num) {
                color_num = color[i];
            }
        }
    }
}

int main()
{
    scanf("%d %d", &node_num, &edge_num);
    int i, j, start, end;
    // 初始化无向图
    for (i = 0; i < node_num; i++) {
        for (j = 0; j < node_num; j++) {
            graph[i][j] = 0;
        }
    }
    // 读入边信息
    for (i = 0; i < edge_num; i++) {
        scanf("%d %d", &start, &end);
        graph[start-1][end-1] = 1;
        graph[end-1][start-1] = 1;
    }
    // 着色
    color_graph();
    printf("Minimum number of colors required: %d\n", color_num);
    printf("Coloring scheme:\n");
    for (i = 0; i < node_num; i++) {
        printf("%d ", color[i]);
    }
    return 0;
}
```

程序输入格式为:

```
节点数 边数
起点1 终点1
起点2 终点2
......
```

例如:

```
5 6
1 2
1 3
2 3
2 4
3 4
4 5
```

程序输出结果为:

```
Minimum number of colors required: 3
Coloring scheme:
1 2 3 1 2 
```

解释:对于给定的无向图,使用3种颜色可以将所有节点着色。最终的着色方案为:节点1的颜色为1,节点2的颜色为2,节点3的颜色为3,节点4的颜色为1,节点5的颜色为2。

python实现:

一、问题描述

图的着色问题是指给定一个无向图,如何为它的每个顶点着色,使得相邻的顶点颜色不同,且使用的颜色数最小。

二、算法思路

图的着色问题可以通过贪心算法来解决。具体来说,对于每个顶点,找出与之相邻的顶点已经使用的颜色,并从未使用的颜色中选择一个最小的颜色进行着色。如果不存在未使用的颜色,则需要新建一个颜色。

三、Python实现

以下是用Python实现图的着色问题的代码:

```python
class Graph:
    def __init__(self, vertices):
        self.V = vertices
        self.graph = [[] for _ in range(vertices)]

    def add_edge(self, u, v):
        self.graph[u].append(v)
        self.graph[v].append(u)

    def get_color(self, v, color):
        used_colors = set([color[i] for i in self.graph[v] if color[i] != -1])
        for c in range(self.V):
            if c not in used_colors:
                return c
        return self.V

    def graph_coloring(self):
        color = [-1] * self.V
        color[0] = 0
        for v in range(1, self.V):
            color[v] = self.get_color(v, color)
        return color
```

在上面的代码中,我们定义了一个Graph类来表示无向图,其中V表示顶点数,graph是一个邻接表,用于存储图的信息。我们使用add_edge方法来添加边。

我们使用get_color方法来获取与顶点v相邻的已经使用的颜色,并从未使用的颜色中选择一个最小的颜色进行着色。如果不存在未使用的颜色,则需要新建一个颜色。

最后,我们使用graph_coloring方法来为所有的顶点着色。我们首先为第一个顶点着色,并遍历所有的顶点来为它们着色。为遍历的每个顶点调用get_color方法来获取它们的颜色,然后将颜色保存到color列表中并返回。

四、测试

下面是一个简单的测试,用于检验图的着色算法的正确性:

```python
g = Graph(5)
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(1, 3)
g.add_edge(2, 3)
g.add_edge(3, 4)

color = g.graph_coloring()

print("Vertex \t Color")
for v in range(g.V):
    print(v, "\t", color[v])
```

输出结果:

```
Vertex 	 Color
0 	 0
1 	 2
2 	 1
3 	 3
4 	 4
```

我们可以看到,这个算法为图中的每个顶点都分配了合适的颜色,而且使用的颜色最小(这里使用了5种颜色,也就是图的顶点数)。

15.城市最短路径问题

16哈夫曼编码问题

17.二分查找问题

18.整数划分问题

19.主定理法求时间复杂度

主定理法(Master Theorem)是计算分治算法时间复杂度的一种通用方法。它的基本思想是将问题分解成更小的子问题,然后递归解决这些子问题,最后再将结果合并起来。主定理法的公式为:

T(n) = a * T(n/b) + f(n)

其中,n是问题规模,a是子问题的个数,b是子问题的规模,f(n)是将子问题的解合并起来所需要的时间复杂度。 

根据主定理法,可以得出以下三种情况:

1. 如果f(n) = O(n^d),且logb(a) < d,则T(n) = O(n^d)。

2. 如果f(n) = O(n^d),且logb(a) = d,则T(n) = O(n^d * log n)。

3. 如果f(n) = O(n^d),且logb(a) > d,则T(n) = O(n^logb(a))。

其中,d是一个常数。

例如,对于快速排序算法,每次将数组分为两半,即a=2,b=2,因此logb(a) = log2(2) = 1。同时,将两个子数组合并的时间复杂度是O(n),因此f(n) = O(n)。根据情况3,可以得出时间复杂度为O(nlogn)。
 

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值