算法设计与分析题目总结

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;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值