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)。