算法课实验
来源:互联网 发布:淘宝卖蜂蜜需要什么 编辑:程序博客网 时间:2024/05/22 03:58
LCS的实验,注释写的比较详细.
#include <stdio.h>#include <string.h>char a[505];//第一个序列char b[505];//第二个序列int dp[505][505];//dp[i][j]是在第一个序列的第i个字母和第二个序列的第j个字母时的最长公共子序列char result[505];//存储解int num;//存储解的个数int main(){ int i,j,n,l1,l2; printf("请输入第一个序列\n"); scanf("%s",a+1);//这里注意由于下标从0开始所以第一个位置空下来否则dp[i-1][j-1]就会越界 printf("请输入第二个序列\n"); scanf("%s",b+1); l1=strlen(a+1); l2=strlen(b+1); memset(dp,0,sizeof(dp));//dp数组清零 for (i=1;i<=l1;i++) for (j=1;j<=l2;j++) if (a[i]==b[j])//如果第一个序列的第i个字母等于第二个序列的第j个字母 dp[i][j]=dp[i-1][j-1]+1; else//如果这两个位置的字母不等,则取dp[i-1][j]和dp[i][j-1]中较大的作为dp[i][j] { if (dp[i-1][j]>dp[i][j-1]) dp[i][j]=dp[i-1][j]; else dp[i][j]=dp[i][j-1]; } printf("最长公共子序列的长度为:%d\n",dp[l1][l2]); if (dp[l1][l2]!=0) { printf("构造的一个解为:%"); //从后面往前面推出解,因为dp[i][j]存储的是上一次到这一次所以有这次的dp[i][j]可得上一次是怎样来的 i=l1; j=l2; num=0; while(i>=1&&j>=1) { if (a[i]==b[j]) { result[num++]=a[i]; i--; j--; } else if (dp[i-1][j]>dp[i][j-1]) i--; else j--; } for (i=num-1;i>=0;i--)//最后要逆序输出 printf("%c",result[i]); } else { printf("无构造解!\n"); } return 0; }
打印全部的最长公共子序列的代码,就是直接在输出时加了一个回溯,但是有些小问题,有时候会重复输出,目前能想到的办法就是放入字符串数组中来判重再输出,比如一条字符串为:bacdca,另一条为:abdca会重复输出.
#include <stdio.h>#include <string.h>char a[505];//第一个序列char b[505];//第二个序列int dp[505][505];//dp[i][j]是在第一个序列的第i个字母和第二个序列的第j个字母时的最长公共子序列char p[505];int num;//存储解的个数int l1,l2;void lcs(int n,int m,char s[],int k);//用来找到所有最长公共子序列int main(){ int i,j,n; printf("请输入第一个序列\n"); scanf("%s",a+1);//这里注意由于下标从0开始所以第一个位置空下来否则dp[i-1][j-1]就会越界 printf("请输入第二个序列\n"); scanf("%s",b+1); l1=strlen(a+1); l2=strlen(b+1); memset(dp,0,sizeof(dp));//dp数组清零 for (i=1;i<=l1;i++) for (j=1;j<=l2;j++) if (a[i]==b[j])//如果第一个序列的第i个字母等于第二个序列的第j个字母 dp[i][j]=dp[i-1][j-1]+1; else//如果这两个位置的字母不等,则取dp[i-1][j]和dp[i][j-1]中较大的作为dp[i][j] { if (dp[i-1][j]>dp[i][j-1]) dp[i][j]=dp[i-1][j]; else dp[i][j]=dp[i][j-1]; } printf("最长公共子序列的长度为:%d\n",dp[l1][l2]); if (dp[l1][l2]!=0) { printf("构造的解为:\n"); //从后面往前面推出解,因为dp[i][j]存储的是上一次到这一次所以有这次的dp[i][j]可得上一次是怎样来的 lcs(l1,l2,p,dp[l1][l2]); } else { printf("无构造解!\n"); } return 0;}void lcs(int n,int m,char s[],int k){ int i; if ((k<1)||(n<1)||(m<1))//找到解了 { for (i=1;i<=dp[l1][l2];i++) printf("%c",s[i]); printf("\n"); return; } else { if (a[n]==b[m]) { s[k--]=a[n]; lcs(n-1,m-1,s,k); } else if (dp[n-1][m]>dp[n][m-1]) { lcs(n-1,m,s,k); } else if (dp[n][m-1]>dp[n-1][m]) { lcs(n,m-1,s,k); } else { lcs(n-1,m,s,k); lcs(n,m-1,s,k); } }}
还有书后练习题的代码,关于硬币找零的问题,稍微注意下初始化。
#include <stdio.h>#include <string.h>int min(int a,int b){ return a<b?a:b;} int main() { int n,m,i,j,k,ans; int v[505]; int dp[505][505]; printf("请输入硬币的种类\n"); scanf("%d",&n); printf("请依次输入硬币面值\n"); for (i=1;i<=n;i++) scanf("%d",&v[i]); printf("待分配的总钱数\n"); scanf("%d",&m); for (i=0;i<=n;i++) for (j=0;j<=m;j++) dp[i][j]=99999; for (i=0;i<=m;i++) dp[i][0]=0;//当钱数为0时一律为0 for (i=1;i<=n;i++) for (j=0;j<=m;j++) { ans=9999; for (k=0;k<=j/v[i];k++) ans=min(ans,dp[i-1][j-k*v[i]]+k); dp[i][j]=ans; } if (dp[n][m]!=9999) printf("最少个数为:%d\n",dp[n][m]); else printf("无法找钱\n"); return 0; }
0 0
- 算法课实验
- 算法实验
- 数据结构与算法实验课--链表
- 算法实验课 lab1 解题报告
- 实验二 分类算法实验
- 算法实验1《分治算法实验》
- 算法实验2《贪心算法实验》
- 算法实验3《动态规划算法实验》
- 算法实验5《算法综合实验》
- 下午算法实验考试
- 排序算法的实验
- 算法实验(整理)
- 算法实验 中缀表达式
- 操作系统 调度算法实验
- RANSAC算法MATLAB实验
- ID3算法实验
- 算法实验:格雷码问题
- 实验 折半查找算法
- CGroup 介绍、应用实例及原理描述
- [C++]最小生成树--Prim算法&Kruskal算法
- Codeforces 165E Compatible Numbers
- 利用labview动态生成树
- Max Time-Delay Neural Networks
- 算法课实验
- 腐蚀和膨胀
- Android基础——广播接收者BroadcastReceiver
- android学习之路---java部分 I/O流
- AndroidManifest.xml配置文件详解
- 【Java】多线程实现方式
- 第10、11周项目1-点、圆、圆柱类族的设计(3)
- 贪心法_1 2016.5.16
- 零碎知识点