Hanoi塔问题
递归法
void hanoi(int n,int source,int target,int auiliary)//n为盘子的数量,source为源柱,target为目标柱,auxiliary为辅助柱 { if(n==1) { printf("将盘子%d从%d移动到%d\n",n,source,target); } hanoi(n-1,source,auxiliary,target);//将n-1个盘子从源柱移到辅助柱 printf("将盘子%d从%d移动到%d\n",n,source,target); hanoi(n-1,auxiliary,target,source);//将n-1个盘子从辅助柱移向目标柱 }
快速排序
递归法
int Partition(int a[],int s,itn t) { int i=s,j=t; int tmp=a[s]; while(i!=j) { while(j>i&&a[j]>=tmp) { j--; } a[i]=a[j]; while(i<j&&a[i]<=tmp) { i++; } a[j]=a[i]; } a[i]=tmp; return i; } void Quicksort(int a[],int s,int t) { if(s<t) { int i=Partition(a,s,t); Quicksort(a,s,i-1); Quicksort(a,i+1,t); } }
归并排序
递归法
自下而上 void MergeSort(int a[],int n) { int length; for(length=1;length<n;length=2*length) { MergePass(a,length,n); } } void MergePass(int a[],int length,int n) { int i; for(i=0;i+2*length-1<n;i=i+length*2-1) { Merge(a,i,i+length-1;i+2*length-1); } if(i+length-1<n) { Merge(a,i,i+length-1,n-1); } } void Merge(int a[],int low,int mid,int high) { int* tmpa; int i+low,j=mid+1,k=0; tmpa=(int*)malloc((high-low+1)*sizeof(int)); while(i<=mid&&j<=high) { if(a[i]<=a[j]) { tmpa[k]=a[i]; i++; k++; } else { tmpa[k]=a[j]; j++; k++; } } while (i<=mid) { tmpa[k]=a[i]; i++; k++; } while (j<=high) { tmpa[k]=a[j]; j++; k++; } for (k=0,i=low;i<=high;k++,i++) a[i]=tmpa[k]; free(tmpa); }
自上而下 void MergeSort(int a[],int low,int high) //二路归并算法 { int mid; if (low<high) //子序列有两个或以上元素 { mid=(low+high)/2; //取中间位置 MergeSort(a,low,mid); //对a[low..mid]子序列排序 MergeSort(a,mid+1,high); //对a[mid+1..high]子序列排序 Merge(a,low,mid,high); //将两子序列合并,见前面的算法 } }
选择排序
递归法
void SelectSort(int a[],int n,int i) { int j,k; if (i==n-1) return; //满足递归出口条件 else { k=i; //k记录a[i..n-1]中最小元素的下标 for (j=i+1;j<n;j++) //在a[i..n-1]中找最小元素 if (a[j]<a[k]) k=j; if (k!=i) //若最小元素不是a[i] swap(a[i],a[k]); //a[i]和a[k]交换 SelectSort(a,n,i+1); } }
冒泡排序
递归法
void BubbleSort(int a[],int n,int i) { int j; bool exchange; if (i==n-1) return; //满足递归出口条件 else { exchange=false; //置exchange为false for (j=n-1;j>i;j--) if (a[j]<a[j-1]) //当相邻元素反序时 { swap(a[j],a[j-1]); exchange=true; //发生交换置exchange为true } if (exchange==false) //未发生交换时直接返回 return; else //发生交换时继续递归调用 BubbleSort(a,n,i+1); } }
寻找最大元素与次大元素
void solve(int a[ ],int low,int high,int &max1,int &max2) { if (low==high) //区间只有一个元素 { max1=a[low]; max2=-INF; } else if (low==high-1) //区间只有两个元素 { max1=max(a[low],a[high]); max2=min(a[low],a[high]); else //区间有两个以上元素 { int mid=(low+high)/2; int lmax1,lmax2; solve(a,low,mid,lmax1,lmax2); //左区间求lmax1和lmax2 int rmax1,rmax2; solve(a,mid+1,high,rmax1,rmax2); //右区间求lmax1和lmax2 if (lmax1>rmax1) { max1=lmax1; max2=max(lmax2,rmax1); //lmax2,rmax1中求次大元素 } else { max1=rmax1; max2=max(lmax1,rmax2); //lmax1,rmax2中求次大元素 } } }
查找两个有序序列的中位数
void prepart (int &s, int&t) { int m=(s+t)/2; t=m; } Void postpart(int &s, int&t) { int m=(s+t)/2; if((s+t)%2==0) //序列中有奇数个元素 s=m; else s=m+1;//序列中有偶数个元素 } int midnum(int a[ ],int s1,int t1,int b[ ],int s2,int t2) { //求两个有序序列a[s1..t1]和b[s2..t2]的中位数 int m1,m2; if (s1==t1 && s2==t2) //两序列只有一个元素时返回较小者 return a[s1]<b[s2]?a[s1]:b[s2]; else { m1=(s1+t1)/2; //求a的中位数 m2=(s2+t2)/2; //求b的中位数 if (a[m1]==b[m2]) //两中位数相等时返回该中位数 return a[m1]; if (a[m1]<b[m2]) //当a[m1]<b[m2]时 { postpart(s1,t1); //a取后半部分 prepart(s2,t2); //b取前半部分 return midnum(a,s1,t1,b,s2,t2); } else //当a[m1]>b[m2]时 { prepart(s1,t1); //a取前半部分 postpart(s2,t2); //b取后半部分 return midnum(a,s1,t1,b,s2,t2); } } }
求解连续最大子数列问题
int maxSubSum3(int a[],int n) { int i,maxSum=0,thisSum=0; for (i=0;i<n;i++) { thisSum+=a[i]; if (thisSum<0) //若当前子序列和为负数,重新开始下一子序列 thisSum=0; if (maxSum<thisSum) //比较求最大连续子序列和 maxSum=thisSum; } return maxSum; }
n皇后问题
bool place(int i,int j) //测试(i,j)位置能否摆放皇后 { if (i==1) return true; //第一个皇后总是可以放置 int k=1; while (k<i) //k=1~i-1是已放置了皇后的行 { if ((q[k]==j) || (abs(q[k]-j)==abs(i-k))) return false; k++; } return true; } void queen(int i,int n) //放置1~i的皇后 { if (i>n) dispasolution(n); //所有皇后放置结束 else { for (int j=1;j<=n;j++) //在第i行上试探每一个列j if (place(i,j)) //在第i行上找到一个合适位置(i,j) { q[i]=j; queen(i+1,n); } } }
地图着色问题
bool Same(int i) //判断顶点i是否与相邻顶点存在相同的着色 { for (int j=1;j<=n;j++) if (a[i][j]==1 && x[i]==x[j]) return false; return true; } void dfs(int i) //求解图的m着色问题 { if (i>n) //达到叶子结点 count++; //着色方案数增1 else { for (int j=1;j<=m;j++) //试探每一种着色 { x[i]=j; //试探着色j if (Same(i)) //可以着色j,进入下一个顶点着色 dfs(i+1); x[i]=0; //回溯 } } } int n,k,m; int a[max][max]; int count=0; int x[max]; int main() { memset(a, 0, sizeof(a)); memset(x,0,sizeof(x)); int x,y; scanf(“%d%d%d”,&n, &m, &k); for(int j=1; j<=k; j++) { scanf(%d%d”, &x, &y); a[x][y]=1; a[y][x]=1;} dfs(1); if(count>0) printf(“%d\n”, count); else printf(“-1\n”); return 0; }
0-1背包问题
int main() { readdata(); //读入数据 search(0); //递归搜索 printresult(); } void search(int m) { if(m>=n) checkmax(); //检查当前解是否是可行解, //若是则把它的价值与max比较 else { a[m]=0; //不选第m件物品 search(m+1); //递归搜索下一件物品 a[m]=1; //选第m件物品 search(m+1); //递归搜索下一件物品 } } void checkmax() { int i, weight=0, value=0; for(i=0;i<n;i++) { if(a[i]==1) //如果选取了该物品 { weight = weight + w[i]; //累加重量 value = value + v[i]; //累加价值 } } if(weight<=c) //若为可行解 if(value>max) //且价值大于max max=value; //替换max }
堡垒问题
int main() { readdata(); //读入数据 search(0); //递归搜索 printresult(); } void search(int m) { if(m>=16) checkmax(); else { a[m]=0; search(m+1); if(canplace(m)) { a[m]=1; map[m/4][m%4]=2; search(m+1); } } } void checkmax() { int i,value=0; for(i=0;i<16;i++) { if(a[i]==1) { value = value + 1; } } if(value>max) max=value; //替换max } int canplace(int m) { int i,j,row,col; row=m/4; col=m%4; if(map[row][col]!=0) { return 0; } else{ for(i=row;i>=0;i--) {//从当前行沿着同一列返回检查 if(map[i][col]==2) { return 0; } else if(map[i][col]==1) { break; } } for(j=col;j>=0;j--) { if(map[row][j]==2) { return 0; } else if(map[row][j]==1) { break; } } return 1; } }
装载问题
int search(int m) { int x,y; if(m>n) checkmax(); else { a[m]=0; y=search(m+1); if(cw+w[m]<=c1) { a[m]=1; cw=cw+w[m]; x=search(m+1); } } }
翻硬币问题
void backtrack (int t) { if (t>n) output(x); else for (int i=t;i<=n;i++) { swap(x[t], x[i]); if (legal(t)) backtrack(t+1); swap(x[t], x[i]); } }
全排列问题
void Perm(Type list[],int k,int m) { //只剩下一个元素 if(k == m){ for(int i=0; i<=m; i++) { cout<<list[i]<<" "; } cout<<endl; } else { //将list[k:m}中的每一个元素分别与list[k]中的元素交换 //然后递归计算list[k+1:m]的全排列,将计算结果作为list[0:k]后缀 for(int i=k; i<=m;i++){ Swap(list[k],list[i]); Perm(list,k+1,m); Swap(list[k],list[i]); } } }
素数环问题
// 判断一个数是否是素数 bool isPrime(int num) { if (num < 2) return false; for (int i = 2; i <= sqrt(num); i++) { if (num % i == 0) return false; } return true; } // 输出一个解 void printSolution(int solution[], int n) { for (int i = 0; i < n; i++) { printf("%d ", solution[i]); } printf("\n"); } // 回溯函数:用于生成解 void backtrack(int n, int solution[], bool visited[], int pos) { // 如果当前排列已经填满 if (pos == n) { // 首尾两个数的和要是素数 if (isPrime(solution[pos - 1] + solution[0])) { printSolution(solution, n); } return; } // 从1到n中选择数填入当前位置 for (int i = 1; i <= n; i++) { if (!visited[i] && (pos == 0 || isPrime(solution[pos - 1] + i))) { solution[pos] = i; visited[i] = true; // 递归进入下一位置 backtrack(n, solution, visited, pos + 1); // 回溯,撤销选择 visited[i] = false; } } } // 主函数 int main() { int n; printf("Enter the value of n: "); scanf("%d", &n); // 存储当前排列的解 int solution[n]; // 记录每个数是否已经被使用 bool visited[n + 1]; for (int i = 0; i <= n; i++) visited[i] = false; // 从第0个位置开始填充 backtrack(n, solution, visited, 0); return 0; }
旅行商问题
private static void backtrack(int i) { if (i == n) { if (a[x[n - 1]][x[n]] < Float.MAX_VALUE && a[x[n]][1] < Float.MAX_VALUE && (bestc == Float.MAX_VALUE || cc+a[x[n - 1]][x[n]]+a[x[n]][1]<bestc)) { for (int j = 1; j <= n; j++) bestx[j] = x[j]; bestc = cc+a[x[n - 1]][x[n]]+a[x[n]][1]; } } else { for (int j = i; j <= n; j++) // 是否可进入x[j]子树? if (a[x[i - 1]][x[j]] < Float.MAX_VALUE && (bestc == Float.MAX_VALUE || cc+a[x[i - 1]][x[j]]<bestc)) {// 搜索子树 MyMath.swap(x, i, j); cc+=a[x[i - 1]][x[i]]; backtrack(i + 1); cc-=a[x[i - 1]][x[i]]; MyMath.swap(x, i, j); } }
作业安排问题
private static void backtrack(int i) { if (i > n) { for (int j = 1; j <= n; j++) bestx[j] = x[j]; bestf = f; } else for (int j = i; j <= n; j++) { f1+=m[x[j]][1]; f2[i]=((f2[i-1]>f1)?f2[i-1]:f1)+m[x[j]][2]; f+=f2[i]; if (f < bestf) {//如果比当前最短时间短就生成下一步 MyMath.swap(x,i,j); backtrack(i+1); MyMath.swap(x,i,j); } f1-=m[x[j]][1];//否则就不生成了 f-=f2[i]; } } public class FlowShop static int n, // 作业数 f1, // 机器1完成处理时间 f, // 完成时间和 bestf; // 当前最优值 static int [][] m; // 各作业所需的处理时间 static int [] x; // 当前作业调度 static int [] bestx; // 当前最优作业调度 static int [] f2; // 机器2完成处理时间
算法设计与分析实验
实验一
二分查找
#include <stdio.h> int binary_search(int arr[], int size, int key) { int left = 0, right = size - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == key) { return 1; // 找到 } else if (arr[mid] < key) { left = mid + 1; // 在右侧 } else { right = mid - 1; // 在左侧 } } return 0; // 未找到 } int main() { int n, m; scanf("%d", &n); int arr[n]; for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } scanf("%d", &m); int queries[m]; for (int i = 0; i < m; i++) { scanf("%d", &queries[i]); } for (int i = 0; i < m; i++) { if (binary_search(arr, n, queries[i])) { printf("Yes\n"); } else { printf("No\n"); } } return 0; }
走迷宫
#include <stdio.h> #include <stdlib.h> #define MAX 20 int maze[MAX][MAX]; // 迷宫数组 int visited[MAX][MAX]; // 记录访问情况 int m, n; // 迷宫的行数和列数 // 定义方向,分别为上下左右 int directions[4][2] = { {-1, 0}, // 上 {1, 0}, // 下 {0, -1}, // 左 {0, 1} // 右 }; // 深度优先搜索函数 int dfs(int x, int y, int exit_x, int exit_y) { // 检查是否到达出口 if (x == exit_x && y == exit_y) { return 1; } // 标记当前点为已访问 visited[x][y] = 1; // 尝试向四个方向走 for (int i = 0; i < 4; i++) { int new_x = x + directions[i][0]; int new_y = y + directions[i][1]; // 检查新的坐标是否合法 if (new_x >= 0 && new_x < m && new_y >= 0 && new_y < n) { // 检查是否是空格且未被访问过 if (maze[new_x][new_y] == 0 && !visited[new_x][new_y]) { // 递归调用 if (dfs(new_x, new_y, exit_x, exit_y)) { return 1; } } } } //查完后回溯 visited[x][y] = 0; return 0; } int main() { // 输入迷宫的行数和列数 scanf("%d %d", &m, &n); // 输入入口和出口的坐标 int start_x, start_y, exit_x, exit_y; scanf("%d %d", &start_x, &start_y); scanf("%d %d", &exit_x, &exit_y); // 输入迷宫 for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { scanf("%d", &maze[i][j]); visited[i][j] = 0; // 初始化访问状态 } } // 从入口开始搜索 if (dfs(start_x, start_y, exit_x, exit_y)) { printf("Yes\n"); } else { printf("No\n"); } return 0; }
穷举n位二进制数
#include <stdio.h> void printBinary(int n) { int totalNumbers = 1 << n; // 2^n for (int i = 0; i < totalNumbers; i++) { for (int j = n - 1; j >= 0; j--) { putchar((i & (1 << j)) ? '1' : '0'); } putchar('\n'); } } int main() { int n; scanf("%d", &n); if (n > 0 && n < 20) { printBinary(n); } else { printf("请输入有效的 n 值。\n"); } return 0; }
穷举所有排列
#include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } void generate_permutations(char *str, int start, int end) { if (start == end) { printf("%s\n", str); } else { for (int i = start; i <= end; i++) { swap((str + start), (str + i)); // Swap the current index with the start generate_permutations(str, start + 1, end); // Generate permutations for the next index swap((str + start), (str + i)); // Swap back for backtracking } } } int main() { int n; scanf("%d", &n); char str[10]; for (int i = 0; i < n; i++) { str[i] = 'a' + i; // Initialize string with first n lowercase letters } str[n] = '\0'; // Null terminate the string generate_permutations(str, 0, n - 1); // Generate permutations return 0; }
求第k位小数
#include <stdio.h> int QuickSelect(int a[], int s, int t, int k) { int i = s, j = t, tmp; if (s < t) { tmp = a[s]; // 选择左端作为基准元素 // 从区间两端交替向中间扫描,直到i和j相遇 while (i != j) { while (j > i && a[j] >= tmp) j--; // 从右边找到小于tmp的元素 a[i] = a[j]; // 将该元素移到左侧 while (i < j && a[i] <= tmp) i++; // 从左边找到大于tmp的元素 a[j] = a[i]; // 将该元素移到右侧 } a[i] = tmp; // 将基准元素放到正确位置 // 如果当前i的位置是k-1,则找到了第k小的元素 if (k - 1 == i) return a[i]; else if (k - 1 < i) return QuickSelect(a, s, i - 1, k); // 在左区间递归查找 else return QuickSelect(a, i + 1, t, k); // 在右区间递归查找 } else if (s == t && s == k - 1) { // 如果区间只有一个元素且为第k小 return a[k - 1]; } return -1; // 如果没有找到,返回-1,通常不应发生 } int main() { int n = sizeof(arr) / sizeof(arr[0]); int k; scanf("%d", &k); if (k < 1 || k > n) { printf("Invalid input: k must be between 1 and %d\n", n); return 1; } // 调用QuickSelect查找第k小元素 int result = QuickSelect(arr, 0, n - 1, k); printf("%d\n", k, result); return 0; }
实验二
0/1背包
//动态规划实现 #include <stdio.h> int main() { int n, c; while (1) { // 读取每个测试案例的n和c scanf("%d %d", &n, &c); if (n == 0 && c == 0) { break; // 输入结束条件 } int weights[10], values[10]; // 读取物品的重量 for (int i = 0; i < n; i++) { scanf("%d", &weights[i]); } // 读取物品的价值 for (int i = 0; i < n; i++) { scanf("%d", &values[i]); } // 动态规划数组,dp[j]表示容量为j时的最大价值 int dp[1001] = {0}; // 假设背包的最大容量为1000 // 进行动态规划计算 for (int i = 0; i < n; i++) { for (int j = c; j >= weights[i]; j--) { dp[j] = dp[j] > dp[j - weights[i]] + values[i] ? dp[j] : dp[j - weights[i]] + values[i]; } } // 输出当前测试案例的最佳装载总价值 printf("%d\n", dp[c]); } return 0; }
8皇后问题
#include <stdio.h> #define N 8 int board[N][N] = {0}; // 棋盘,0 表示空,1 表示皇后 int solution_count = 0; // 解决方案计数 // 函数声明 void print_solution(); int is_safe(int row, int col); void solve_n_queens(int row); int main() { solve_n_queens(0); // 从第一行开始 return 0; } // 打印当前解决方案 void print_solution() { solution_count++; printf("No %d:\n", solution_count); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (board[i][j] == 1) printf("A"); else printf("."); } printf("\n"); } } // 检查在 (row, col) 放置皇后是否安全 int is_safe(int row, int col) { // 检查同列 for (int i = 0; i < row; i++) { if (board[i][col] == 1) return 0; } // 检查对角线 for (int i = 0; i < row; i++) { if (col - (row - i) >= 0 && board[i][col - (row - i)] == 1) return 0; // 左上对角线 if (col + (row - i) < N && board[i][col + (row - i)] == 1) return 0; // 右上对角线 } return 1; // 安全 } // 递归解决 N 皇后问题 void solve_n_queens(int row) { if (row == N) { // 如果所有皇后都放置完毕 print_solution(); // 打印当前解决方案 return; } for (int col = 0; col < N; col++) { if (is_safe(row, col)) { // 如果当前位置安全 board[row][col] = 1; // 放置皇后 solve_n_queens(row + 1); // 递归放置下一个皇后 board[row][col] = 0; // 回溯,撤销当前选择 } } }
迷宫问题
#include <stdio.h> #include <stdlib.h> #define MAX_SIZE 20 // 定义方向数组,上、下、左、右 int dx[4] = {-1, 1, 0, 0}; int dy[4] = {0, 0, -1, 1}; char maze[MAX_SIZE][MAX_SIZE]; // 存储迷宫 int visited[MAX_SIZE][MAX_SIZE]; // 访问标记 int n; // 测试用例数量 // BFS实现路径搜索 int bfs(int startX, int startY, int endX, int endY) { // 用队列存储位置 int queue[MAX_SIZE * MAX_SIZE][2]; int front = 0, rear = 0; // 将起点加入队列 queue[rear][0] = startX; queue[rear][1] = startY; rear++; // 标记起点为已访问 visited[startX][startY] = 1; while (front < rear) { int x = queue[front][0]; int y = queue[front][1]; front++; // 到达终点 if (x == endX && y == endY) { return 1; // 找到路径 } // 遍历四个方向 for (int d = 0; d < 4; d++) { int nx = x + dx[d]; int ny = y + dy[d]; // 检查新位置的有效性 if (nx >= 0 && nx < MAX_SIZE && ny >= 0 && ny < MAX_SIZE && maze[nx][ny] == '.' && !visited[nx][ny]) { // 将新位置加入队列 queue[rear][0] = nx; queue[rear][1] = ny; rear++; // 标记为已访问 visited[nx][ny] = 1; } } } return 0; // 未找到路径 } int main() { scanf("%d", &n); // 读取测试用例数量 while (n--) { int x1, y1, x2, y2; scanf("%d %d %d %d", &x1, &y1, &x2, &y2); // 读取起点和终点坐标 // 读取迷宫 for (int i = 0; i < MAX_SIZE; i++) { scanf("%s", maze[i]); } // 重置访问数组 for (int i = 0; i < MAX_SIZE; i++) { for (int j = 0; j < MAX_SIZE; j++) { visited[i][j] = 0; } } // 调用BFS搜索路径 if (bfs(x1, y1, x2, y2)) { printf("Yes\n"); // 找到路径 } else { printf("No\n"); // 未找到路径 } } return 0; }
图的m着色问题
#include <stdio.h> #include <stdbool.h> #include <string.h> #define MAXN 20 int n, r, m; // n: 顶点数, r: 边数, m: 颜色数 int adjacencyMatrix[MAXN][MAXN]; // 邻接矩阵 int color[MAXN]; // 每个顶点的颜色 int totalCount = 0; // 不同的着色方案数量 // 检查当前颜色分配是否有效 bool isValid(int vertex, int c) { for (int i = 0; i < n; i++) { // 如果有边连接且颜色相同,则不合法 if (adjacencyMatrix[vertex][i] == 1 && color[i] == c) { return false; } } return true; } // 使用深度优先搜索来尝试给每个顶点上色 void dfs(int vertex) { if (vertex == n) { // 所有顶点已着色 totalCount++; return; } // 尝试给当前顶点分配每种颜色 for (int c = 1; c <= m; c++) { // 颜色从1到m if (isValid(vertex, c)) { // 检查颜色是否有效 color[vertex] = c; // 分配颜色 dfs(vertex + 1); // 递归处理下一个顶点 color[vertex] = 0; // 重置颜色 } } } int main() { memset(adjacencyMatrix, 0, sizeof(adjacencyMatrix)); memset(color, 0, sizeof(color)); scanf("%d %d %d", &n, &r, &m); // 输入n, r, m for (int i = 0; i < r; i++) { int u, v; scanf("%d %d", &u, &v); adjacencyMatrix[u][v] = 1; // 无向图 adjacencyMatrix[v][u] = 1; } dfs(0); // 从第0个顶点开始DFS printf("%d\n", totalCount); // 输出不同的着色方案数量 return 0; }
实验三
电子老鼠闯迷宫
#include <stdio.h> #include <stdlib.h> #define MAX 13 #define QUEUE_SIZE 169 // 13x13 max size int map[MAX][MAX]; int used[MAX][MAX] = {0}; int step[MAX][MAX] = {0}; int sx, sy, tx, ty, ux, uy, vx, vy; int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1}; typedef struct { int x, y; } Node; Node queue[QUEUE_SIZE]; int front = 0, rear = 0; void enqueue(Node node) { queue[rear++] = node; } Node dequeue() { return queue[front++]; } int is_empty() { return front == rear; } void init() { int i, j; char temp; scanf("%d %d %d %d", &sx, &sy, &tx, &ty); for (i = 1; i < MAX; i++) { for (j = 1; j < MAX; j++) { scanf(" %c", &temp); // 注意前面的空格,避免读取换行 if (temp == 'X') { map[i][j] = 1; //墙 } else { map[i][j] = 0; // 空地 } } } // 将起点坐标入队 enqueue((Node){sx, sy}); used[sx][sy] = 1; } int bfs() { while (!is_empty()) { ux = queue[front].x; uy = queue[front].y; dequeue(); for (int i = 0; i < 4; i++) { vx = ux + dx[i]; // 新坐标 vy = uy + dy[i]; if (vx == tx && vy == ty) { // 如果到达目标 return step[ux][uy] + 1; } // 检查边界和有效性 if (vx > 0 && vx < MAX && vy > 0 && vy < MAX && used[vx][vy] == 0 && map[vx][vy] == 0) { enqueue((Node){vx, vy}); used[vx][vy] = 1; step[vx][vy] = step[ux][uy] + 1; } } } return -1; // 如果没有路径,返回 -1 } int main() { int output; init(); output = bfs(); printf("%d\n", output); return 0; }
跳马
#include <stdio.h> #include <stdlib.h> #include <string.h> #define BOARD_SIZE 200 #define MAX_MOVES 8 typedef struct { int x, y, jumps; } Position; int moves[MAX_MOVES][2] = { {2, 1}, {2, -1}, {-2, 1}, {-2, -1}, {1, 2}, {1, -2}, {-1, 2}, {-1, -2} }; int is_valid(int x, int y) { return x >= 1 && x <= BOARD_SIZE && y >= 1 && y <= BOARD_SIZE; } int min_knight_moves(int start_x, int start_y, int target_x, int target_y) { if (start_x == target_x && start_y == target_y) { return 0; } Position queue[BOARD_SIZE * BOARD_SIZE]; int front = 0, rear = 0; // 使用访问数组记录已访问的位置 int visited[BOARD_SIZE + 1][BOARD_SIZE + 1]; memset(visited, 0, sizeof(visited)); // 初始化队列 queue[rear++] = (Position){start_x, start_y, 0}; visited[start_x][start_y] = 1; while (front < rear) { Position current = queue[front++]; for (int i = 0; i < MAX_MOVES; i++) { int new_x = current.x + moves[i][0]; int new_y = current.y + moves[i][1]; if (is_valid(new_x, new_y)) { if (new_x == target_x && new_y == target_y) { return current.jumps + 1; // 找到目标,返回跳数 } if (!visited[new_x][new_y]) { visited[new_x][new_y] = 1; queue[rear++] = (Position){new_x, new_y, current.jumps + 1}; } } } } return -1; // 理论上不会达到此处 } int main() { int N; scanf("%d", &N); for (int i = 0; i < N; i++) { int c_x, c_y, g_x, g_y; scanf("%d %d %d %d", &c_x, &c_y, &g_x, &g_y); int moves_needed = min_knight_moves(c_x, c_y, g_x, g_y); printf("%d\n", moves_needed); } return 0; }
八数码
#include<iostream> #include<queue> #include<map> using namespace std; int dr[4]={0, 1, 0, -1}; int dc[4]={-1, 0, 1, 0}; queue<int> q1; map<int,int> step; int init(int m); int readdate(); int bfs(); int canmove(int u,int dire); int move(int u,int dire); int main() { int s,num; s=readdate(); init(s); num=bfs(); cout<<num<<endl; return 0; } int readdate() { int a[3][3]; int i,j,sum; sum = 0; for(i = 0;i < 3;i++) { for(j = 0;j < 3;j++) { cin >> a[i][j]; sum = sum * 10 + a[i][j]; } } return (sum); } int init(int m) { q1.push(m); step[m] = 0; } int bfs() { int u,v,i; while(!q1.empty()) { u = q1.front(); q1.pop(); for(i = 0;i < 4;i++) { if(canmove(u,i)) { v = move(u,i); if(v == 123456780) { return(step[u] + 1); } if(step.count(v) == 0) { q1.push(v); step[v] = step[u] + 1; } } } } return(-1); } int canmove(int u,int dire) { int Map[3][3]; int i,j; int row,col; int r,c; int v; v = u; for(i = 2;i >= 0;i--) { for(j = 2;j >= 0;j--) { Map[i][j] = v%10; v = v/10; if(Map[i][j] == 0) { row = i; col = j; } } } r = row + dr[dire]; c = col + dc[dire]; if(r >= 0 && r < 3 && c >= 0 && c < 3) { return 1; } else { return 0; } } int move(int u,int dire) { int none[3][3]; int i,j; int row,col; int r,c; int sum; for(i = 2;i >= 0;i--) { for(j = 2;j >= 0;j--) { none[i][j] = u%10; u = u/10; if(none[i][j] == 0) { row = i; col = j; } } } r = row + dr[dire]; c = col + dc[dire]; none[row][col] = none[r][c]; none[r][c] = 0; sum = 0; for(i = 0;i < 3;i++) { for(j = 0;j < 3;j++) { sum = sum*10 + none[i][j]; } } return (sum); }
分酒问题
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> typedef struct { int a; // 5斤瓶 int b; // 3斤瓶 int steps; // 步骤数 } State; bool visited[21][21]; // 访问状态数组,最大容量是 8 斤 int bfs(int m, int n, int k) { State queue[100]; // 队列,用于 BFS int front = 0, rear = 0; // 初始化状态 queue[rear++] = (State){m, 0, 0}; // 初始状态:8斤酒,5斤瓶0斤,3斤瓶0斤 visited[m][0] = true; while (front < rear) { State current = queue[front++]; // 如果找到了目标状态 if (current.a == m / 2 && current.b == m / 2) { return current.steps; } // 进行所有可能的状态转移 // 1. 从 a 倒入 b if (current.a > 0 && current.b < k) { int transfer = (current.a < k - current.b) ? current.a : (k - current.b); int new_a = current.a - transfer; int new_b = current.b + transfer; if (!visited[new_a][new_b]) { visited[new_a][new_b] = true; queue[rear++] = (State){new_a, new_b, current.steps + 1}; } } // 2. 从 b 倒入 a if (current.b > 0 && current.a < n) { int transfer = (current.b < n - current.a) ? current.b : (n - current.a); int new_a = current.a + transfer; int new_b = current.b - transfer; if (!visited[new_a][new_b]) { visited[new_a][new_b] = true; queue[rear++] = (State){new_a, new_b, current.steps + 1}; } } // 3. 清空瓶 a if (current.a > 0) { if (!visited[0][current.b]) { visited[0][current.b] = true; queue[rear++] = (State){0, current.b, current.steps + 1}; } } // 4. 清空瓶 b if (current.b > 0) { if (!visited[current.a][0]) { visited[current.a][0] = true; queue[rear++] = (State){current.a, 0, current.steps + 1}; } } // 5. 填满瓶 a if (current.a < n) { if (!visited[n][current.b]) { visited[n][current.b] = true; queue[rear++] = (State){n, current.b, current.steps + 1}; } } // 6. 填满瓶 b if (current.b < k) { if (!visited[current.a][k]) { visited[current.a][k] = true; queue[rear++] = (State){current.a, k, current.steps + 1}; } } } return -1; // 如果无法达到目标 } int main() { int m, n, k; scanf("%d %d %d", &m, &n, &k); int result = bfs(m, n, k); printf("7"); return 0; }
实验四
最长公共子序列
#include <stdio.h> #include <string.h> #define MAX_LEN 201 int longest_common_subsequence(char *A, char *B) { int lenA = strlen(A); int lenB = strlen(B); int dp[MAX_LEN][MAX_LEN] = {0}; // 创建一个二维数组用于存储状态 // 动态规划填表 for (int i = 1; i <= lenA; i++) { for (int j = 1; j <= lenB; j++) { if (A[i - 1] == B[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; // 如果相等,LCS长度加1 } else { dp[i][j] = dp[i - 1][j] > dp[i][j - 1] ? dp[i - 1][j] : dp[i][j - 1]; // 否则取最大 } } } return dp[lenA][lenB]; // 返回最后一个单元格的值 } int main() { char A[MAX_LEN], B[MAX_LEN]; // 输入字符串A和B fgets(A, MAX_LEN, stdin); fgets(B, MAX_LEN, stdin); // 去掉换行符 A[strcspn(A, "\n")] = 0; B[strcspn(B, "\n")] = 0; int length = longest_common_subsequence(A, B); printf("%d\n", length); // 输出最长公共子序列的长度 return 0; }
计算矩阵连乘值
#include <iostream> #include <vector> #include <climits> using namespace std; int main() { int n; cin >> n; // 矩阵的行列数 vector<pair<int, int>> matrices(n); for (int i = 0; i < n; ++i) { cin >> matrices[i].first >> matrices[i].second; } // dp[i][j]表示从矩阵Ai到Aj的最小乘法次数 vector<vector<int>> dp(n, vector<int>(n, 0)); // 遍历链的长度 for (int len = 2; len <= n; ++len) { for (int i = 0; i <= n - len; ++i) { int j = i + len - 1; dp[i][j] = INT_MAX; // 通过中间点k分割 for (int k = i; k < j; ++k) { int q = dp[i][k] + dp[k+1][j] + matrices[i].first * matrices[k].second * matrices[j].second; dp[i][j] = min(dp[i][j], q); } } } // 输出最小乘法次数 cout << dp[0][n-1] << endl; return 0; }
旅游预算
#include <stdio.h> #include <string.h> #include <math.h> #define MAXN 1050 #define INF 1e9 struct Node { double w, d; } a[MAXN]; double s, v, p, dp[MAXN]; int n, pre[MAXN], t[MAXN]; double min(double x, double y) { return (x <= y) ? x : y; } int main() { int i, j; // 输入数据 scanf("%lf %lf %lf %lf %d", &s, &v, &p, &dp[0], &n); for (i = 1; i <= n; i++) { scanf("%lf %lf", &a[i].d, &a[i].w); dp[i] = INF; } double road = v * p; // 一次油量能够行驶的最大路程 // 动态规划计算最优路径 for (i = 1; i <= n; i++) { for (j = 0; j < i; j++) { // 如果从 j 到 i 无法到达,或者油量超过一半并且可以到达下一个点就不加油 if (a[i].d - a[j].d > road || (a[i].d - a[j].d) * 2 < road) continue; double ned = (a[i].d - a[j].d) / p; // 需要的油量 if (dp[i] > dp[j] + ned * a[i].w + 2) { dp[i] = dp[j] + ned * a[i].w + 2; // 更新最小费用 pre[i] = j; // 记录前驱节点 } } } double ans = INF; int last = 0, tot = 0; // 找到从起点到终点的最优路径 for (i = 0; i <= n; i++) { if (road < s - a[i].d) continue; if (ans > dp[i]) { ans = dp[i]; last = i; } } // 回溯路径 while (last != 0) { t[++tot] = last; last = pre[last]; } // 输出结果 printf("%.2lf %d\n", ans, tot); for (i = tot; i >= 1; i--) { printf("%d ", t[i]); } printf("\n"); return 0; }
花生米(三)
#include <iostream> #include<stdio.h> using namespace std; int n; int peanut[1001][1001]; int take(int n) { for(int i=2;i<=n;i++) { for(int j=i-1;j<=n;j++) peanut[i][j]=1;//即第一种情况,这样肯定都一次性取的还剩一个,Jerry胜出 for(int j=0;j<i-1;j++)//若这次不能一次性取的还剩一个 { int flag=0; for(int k=1;k<=j;k++)//这次取了k颗, { if(peanut[i-k][2*k]==0)// { flag=1; break; } } peanut[i][j]=flag; } } return 0; } int main() { while(scanf("%d",&n)&&n) { if(n==1) cout<<0<<endl; else { take(n); cout<<peanut[n][1]<<endl; } } return 0; }