ACM常用代码总结
从给定的文件信息中,我们可以提炼出两个关键的ACM编程知识点:动态规划(Dynamic Programming,简称DP)在字符串匹配中的应用以及图遍历算法在寻找路径问题中的使用。 ### 1. 动态规划在字符串匹配中的应用 #### 代码示例:《Human Gene Functions》(题目编号:1080) 该代码示例主要解决的是DNA序列比对问题,即如何找到两个DNA序列之间的最大匹配得分。这个问题通常出现在生物信息学中,但其解决思路同样适用于一般的字符串匹配问题。 **代码解析**: 1. **状态定义**:`f[i,j]`表示序列`s1[1..i]`与`s2[1..j]`的最大匹配得分。 2. **边界条件**: - 当`i=j=0`时,`f[0,0]=0`,即空串与空串的匹配得分为0。 - 当`i=0`时,`f[0,j]`表示`s1`为空串时,`s2`与`s1`的匹配得分,初始化为`f[0,j-1]+score['-'][s2[j]]`。 - 同理,当`j=0`时,`f[i,0]`的初始化方式类似。 3. **状态转移方程**: - `s1`取第`i`个字符,`s2`不取任何字符:`f[i-1,j]+score[s1[i],'-']` - `s1`不取任何字符,`s2`取第`j`个字符:`f[i,j-1]+score['-',s2[j]]` - `s1`与`s2`都取各自第`i`和`j`个字符:`f[i-1,j-1]+score[s1[i],s2[j]]` - 最终状态转移方程为:`f[i,j]=max(f[i-1,j]+score[s1[i],'-'], f[i,j-1]+score['-',s2[j]], f[i-1,j-1]+score[s1[i],s2[j]])` #### 实际应用: 动态规划在这里的应用非常典型,通过递推的方式避免了重复计算,提高了算法效率。在实际的生物信息学研究中,这种算法可以用于比较不同物种或个体间的基因相似度,是基因组学、蛋白质组学等领域的基础算法之一。 ### 2. 图遍历算法在寻找路径问题中的应用 #### 代码示例:《Snow》(题目编号:1088) 这段代码示例解决了在一个网格地图上寻找从起点到任意位置的最长路径的问题,其中路径上的每个格子都有一个高度值,且只能向高度更低的格子移动。 **代码解析**: 1. **状态定义**:`travel[x][y]`表示坐标`(x,y)`是否被访问过,`value[x][y]`存储从`(x,y)`出发的最长路径长度。 2. **递归函数**:`find_rout(int x, int y)`,用于计算从坐标`(x,y)`出发的最长路径长度。 3. **边界检查**:如果`x`或`y`超出地图范围,则返回0。 4. **状态转移**:如果当前格子已经访问过,则直接返回`value[x][y]`;否则,对每个方向进行遍历,如果当前位置的高度高于邻居的高度,则递归调用`find_rout()`函数,并更新`max_rout`变量。 5. **标记访问**:在计算完从`(x,y)`出发的最长路径后,标记`travel[x][y]`为真,并将结果存储在`value[x][y]`中。 #### 实际应用: 这类问题在游戏开发、地图导航等领域有广泛的应用,比如计算游戏中角色能够达到的最远距离,或是规划导航中的最优路径。通过深度优先搜索(DFS)结合记忆化技术,可以有效地避免重复计算,提高求解效率。 这两个示例不仅展示了ACM竞赛中常见的编程技巧,还体现了这些技术在实际问题解决中的应用价值,对于提升算法理解和编程实践能力具有重要意义。
经过了一段时间的努力,我再Pku上也算是有了一个阶段性的总结拉,下面是我就这段时间搞ACM来的一些代码的总结,具体的一些题目类型的总结看本Blog的相关文章。
huicpc26 ACM_PKU 代码总结
1、DP(动态规划)
/*1080-HumanGeneFunctions.cpp*/
观察题目给出的一个最优解:
AGTGATG
-GTTA-G
将其从某一处切开,如果左边部分的分值不是最大,那么将其进行调整,使其分值变大,
则整个解分值变大,与已知的最优矛盾。所以左边部分的分值必是最大。
同理,右边也是。可见满足最优子结构的性质。考虑使用DP:
设两个DNA序列分别为s1,s2,长度分别为len1,len2,score为分值表。
f[i,j]表示子串s1[1..i]和s2[1..j]的分值。考虑一个f[i,j],我们有:
1.s1取第i个字母,s2取“-”:f[i-1,j] + score[s1[i],''-'']
2.s1取“-”,s2取第j个字母:f[i,j-1] + score[''-'',s2[j]]
3.s1取第i个字母,s2取第j个字母:f[i-1,j-1] + score[s1[i],s2[j]]
即f[i,j] = max(f[i-1,j] + score[s1[i],''-''], f[i,j-1] + score[''-'',s2[j]], f[i-1,j-1] + score[s1[i],s2[j]]);
然后考虑边界条件,这道题为i或j为0的情况。
当i=j=0时,即为f[0,0],这是在计算f[1,1]时用到的,根据f[1,1] = f[0,0] + score[s1[i], s2[j]],明显有f[0,0] = 0。
当i=0时,即为f[0,1..len2],有了f[0,0],可以用f[0,j] = f[0,j-1] + table[''-'',s2[j]]来计算。
当j=0时,即为f[1..len1,0],有了f[0,0],可以用f[i,0] = f[i-1,0] + table[s1[i],''-'']来计算。
至于计算顺序,只要保证计算f[i,j]的时候,使用到的f[i-1,j],f[i,j-1],f[i-1,j-1]都计算出来了就行了。
所谓划分阶段也就是为了达到这个目的。这样我们使用一个二重循环就可以了。*/
#include
#include
#include
using namespace std;
int ctoi(char a){
int b;
if(a==''A'') b = 0;
if(a==''C'') b = 1;
if(a==''G'') b = 2;
if(a==''T'') b = 3;
if(a==''-'') b = 4;
return b;
}
int main()
{
int t,j,k,m,n;
int f1,f2,f3;
int f[101][101];
int arr[5][5]={{5,-1,-2,-1,-3},{-1,5,-3,-2,-4},{-2,-3,5,-2,-2},{-1,-2,-2,5,-1},{-3,-4,-2,-1,0}};
string a,b;
cin>>t;
while(t--){
j = k = 0;
memset(f,0,sizeof(f));
cin>>m>>a;
cin>>n>>b;
for(j=0;j<=m;j++)
{
for(k=0;k<=n;k++)
{
if(j == 0 && k == 0)
{
f[j][k] = 0;
剩余31页未读,继续阅读
- juefeng1232014-07-09重复率太高
- helloid1232011-09-16说实话,首先这些代码基本都是C的,很少一部分C++的,然后就是代码确实质量不怎么高,很多在其他资料中都重复 了
- 粉丝: 1
- 资源: 29
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助