您的位置:首页 > 其它

最长递增子序列 编辑距离问题 青蛙过桥 寻宝路线 回文串问题 租用游艇问题 数字三角形 至多删三个字符

2018-11-06 20:35 387 查看

最长递增子序列 编辑距离问题 青蛙过桥 寻宝路线 回文串问题 租用游艇问题 数字三角形 至多删三个字符

/*弗洛伊德算法(三重循环,中间变量, 起始点, 重点循环顺序) */

1.最长递增子序列:o(N^2)

a[],     len1 = strlen(a)
b[] = {1}   记录I点的最长递增序列;
for(i = 1; i < len1; i++)
{
for(j = 0; j < i; j++)
{
if(a[i] > a[j] && b[i] < b[j]+1)//b[i] 等于(所有小于的数的最长子序列的长度)+ 1
{
b[i] = b[j] + 1;
}
}
}

2 编辑距离问题 (30 分)
设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。
这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。
将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。

dd[i][j]//a串0-i变到b串的0-j的最短编辑问题;

for(i = 0; i <= len1; i++)//某一个串到了0,能一个串剩下的都要删掉,所以编辑距离为i;
{
dd[0][i] = i;
dd[i][0] = i;
}
for(i = 1; i <= len1; i++)
{
for(j = 1; j <= len2; j++)
{
if(a[i] == b[j])    t = 0;
else	t = 1;
dd[i][j] = min(dd[i-1][j]+1, dd[i][j-1]+1, dd[i-1][j-1] + t);// min 找出三个数最小的值,三个值分别是插入一个, 删一个,
//改变一个;
}
}
cout<<dd[len1][len2];

3 青蛙过桥 (25 分)
一座长度为n的桥,起点的一端坐标为0,且在整数坐标i处有a[i]个石头【0<=a[i]<=4】,
一只青蛙从坐标0处开始起跳,一步可以跳的距离为1或2或3【即每一步都会落在整数点处】,
青蛙落在i处会踩着该点的所有石头,求青蛙跳出这座桥最少踩多少个石头?并且输出依次跳
过的坐标点路线,如果存在多种路线,输出字典序最小的那一条。

输入格式:
第一行整数n(<150000),接着下一行会有n+1个由空格隔开的整数,即桥上各个坐标处石头数量。

输出格式:
第一行为踩着最少石头个数,第二行为依次跳过的坐标点【字典序最小的】。

输入样例:
在这里给出两组输入。例如:

10
1 2 1 3 0 3 1 2 1 1 2
100
1 2 0 4 0 1 3 4 2 2 1 3 1 4 0 3 0 1 2 3 3 2 2 0 1 0 0 0 0 1 2 1 3 4 0 3 4 4 1 0
4 1 3 1 1 2 3 4 4 4 0 2 0 1 1 1 3 1 3 2 1 2 4 1 2 1 4 1 0 0 1 2 3 0 2 4 4 0 0 4
2 0 0 2 1 3 3 3 0 0 2 0 0 1 2 4 2 2 2 4 0

void ff(int n)// 这个函数作用就是自底向上递推求踩点数最少;
{
int t, j, i;
for(i = n; i >= 1; i–)
{
t = Max(c[1], c[2], c[3]);
j = c[t];

c[3] = c[2];
c[2] = c[1];
c[1] = j + a[i];
b[i] = c[1];
}

}

void fff(int n, int k)// n 代表桥的总数, K代表当前在那个点上;
//此函数的作用是负责输入路线,
{
int t;
if(n - 3 >= k)
{
if(k == 1)
cout<<k-1;
else	cout<<" "<<k-1;
t = Max(b[k+1], b[k+2], b[k+3]);//max 函数就是求三个数最大值,
fff(n, k+t);
}
else
{
cout<<" "<<k-1;
}

}

4 寻宝路线 (40 分)
在一个m行n列方格矩阵中,每一个方格内摆放着价值不等的宝贝(价值可正可负)
,让小明感到好奇的是,从左上角到达右下角的所有可能路线中,能捡到宝贝的价值总和最大是多少?
而且这种达到最大值的路线 又有多少条?【注意:只能从一个格子向下或向右走到相邻格子,并且走到的格子宝贝一定会被捡起。】

输入格式:
第一行为整数m,n(均不大于100),下一行开始会有一个m行n列的整数方阵,对应方格矩阵中的宝贝价值(这些值的绝对值都不超过500)。

输出格式:
单独一行输出2个整数,分别为能捡到宝贝价值总和的最大值和达到最大值的路线数量,2个整数间隔一个空格。

输入样例:
在这里给出一组输入。例如:

4 5
2 -1 6 -2 9
-3 2 5 -5 1
5 8 3 -2 4
5 2 8 -4 7

可能看着比较复杂,只是条件控制语句没有优化;

void fff(int x, int y, int n, int m)// m, n 很显然是问题的规模,x, y是当前的在的左边,都是从坐标1,1 开始的
{
if(x > 0 && x <= n && y > 0 && y <= m)
{
if(x == n && y == m)
{	}
else
{
if(x + 1 > n)
{
if(y +1 > n)
{
}
else fff(x, y+1, n, m);
}
else
{
if(y+1 > n)
fff(x+1, y, n, m);
else
{
if(b[x][y+1] == b[x+1][y])
{
z++;
fff(x, y+1, n, m);
fff(x+1, y, n, m);
}
else
{
if(b[x+1][y] > b[x][y+1])
fff(x+1, y, n, m);
else	fff(x, y+1, n, m);
}
}
}

}
}

}

5 回文串问题 (25 分)
一个字符串,如果从左到右读和从右到左读是完全一样的,比如"aba",我们称其为回文串。
现在给你一个字符串,可在任意位置添加字符,求最少添加几个字符,才能使其变成一个回文串。

输入格式:
任意给定的一个字符串,其长度不超过1000.

输出格式:
能变成回文串所需添加的最少字符数。

输入样例:
在这里给出一组输入。例如:

Ab3bd
Abb

# include<iostream>
# include<cstring>
using namespace std;

int d[1001][1001];//都初始化为-1;

int ff(string a, int x, int y)//x, y分别代表起点和终点,此程序是从首尾两端同时向中间推的;
{
int i, j;
if(x <= y)
{
if(a[x] == a[y])//首尾相等进行下一个,
{
if(d[x+1][y-1] != -1)
{
d[x][y] = d[x+1][y-1];
return d[x][y];
}
else
{
d[x][y] = ff(a, x+1, y-1);
return d[x][y];
}
}
else//不相等,左添加一个,或右边添加一个;
{
if(d[x+1][y] != -1)
i = d[x+1][y] + 1;
else    i = ff(a, x+1, y) + 1;

if(d[x][y-1] != -1)    j = d[x][y-1] + 1;
else	j = ff(a, x, y-1) + 1;

d[x][y] = i > j ? j : i;
return d[x][y];
}
}
else
return 0;
}
int main()
{

int i, j;
string a;
cin>>a;
for(i = 0; i <= 1000; i++)
memset(d[i], -1, 4*1000);
int len = a.size();

cout<<ff(a, 0, len-1);
return 0;
}

6 租用游艇问题 (15 分)
题目来源:王晓东,《算法设计与分析》

长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,
并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i<j<=n。
试设计一个算法,计算出从游艇出租站1 到游艇出租站n所需的最少租金。

输入格式:
第1 行中有1 个正整数n(n<=200),表示有n个游艇出租站。接下来的第1到第n-1 行,第i行表示第i站到第i+1站,第i+2站, … , 第n站的租金。

输出格式:
输出从游艇出租站1 到游艇出租站n所需的最少租金。

输入样例:
在这里给出一组输入。例如:

3
5 15
7
输出样例:
在这里给出相应的输出。例如:

12

//实际上是用的回溯算法;
# include

using namespace std;

int a[200][200];
int max1 = 100000000;
int num = 0;

void ff(int n, int k)
{
int i;
if(k <= n)
{
for(i = k+1; i <= n; i++)
{
num += a[k][i];
ff(n, i);
num -= a[k][i];
}
}
if(k == n)
{
if(num < max1)  max1 = num;
}
}

int main()
{
int i, j, n;
scanf("%d", &n);
for(i = 1; i < n; i++)
{
for(j = i+1; j <= n; j++)
scanf("%d", &a[i][j]);
}
ff(n, 1);
printf("%d", max1);

return 0;
}

7 数字三角形 (30 分)
给定一个由 n行数字组成的数字三角形如下图所示。试设计一个算法,
计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大。

输入格式:
输入有n+1行:

第 1 行是数字三角形的行数 n,1<=n<=100。

接下来 n行是数字三角形各行中的数字。所有数字在0…99 之间。

输出格式:
输出最大路径的值。

输入样例:
在这里给出一组输入。例如:

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
在这里给出相应的输出。例如:

30
//循环性写法,C

# include<stdio.h>

int a[105][105];
int b[105][105];
int max(int a, int b)
{
return a > b ? a : b;
}

int main()
{
int i, j;
int n;
scanf("%d", &n);
for(i = 1; i <= n; i++)
{
for(j = 1; j <= i; j++)
scanf("%d", &a[i][j]);
}

for(i = 1; i <= n; i++)
b
[i] = a
[i];
for(i = n-1; i >= 1; i--)
{
for(j = 1; j <= i; j++)
{
b[i][j] = max(b[i+1][j], b[i+1][j+1]) + a[i][j];
}
}
printf("%d", b[1][1]);
return 0;
}

8 至多删三个字符 (35 分)
给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串?

输入格式:
输入在一行中给出全部由小写英文字母组成的、长度在区间 [4, 10
?6
?? ] 内的字符串。

输出格式:
在一行中输出至多删掉其中 3 个字符后不同字符串的个数。

输入样例:
ababcc
输出样例:
25
提示:

删掉 0 个字符得到 “ababcc”。

删掉 1 个字符得到 “babcc”, “aabcc”, “abbcc”, “abacc” 和 “ababc”。

删掉 2 个字符得到 “abcc”, “bbcc”, “bacc”, “babc”, “aacc”, “aabc”, “abbc”, “abac” 和 “abab”。

删掉 3 个字符得到 “abc”, “bcc”, “acc”, “bbc”, “bac”, “bab”, “aac”, “aab”, “abb” 和 “aba”。

作者: 曹鹏
单位: Google
时间限制: 400 ms
内存限制: 64 MB

#include<bits/stdc++.h>
#define N 1000002

typedef long long LL;
char S
;
LL F
[4];

/*LL dp1(int i,int j)//由于i可达到100万,递归深度会超出 ,所以要写成循环型
{
if(j<0||j>i)    return 0;
if(F[i][j])     return F[i][j];
if(j==0||j==i)  return F[i][j]=1;
else
{
int k,t=0;
for(k=i-1;k>=i-j;k--)
if(S[k]==S[i])  { t=f(k-1,j+k-i); break;}
return F[i][j] = f(i-1,j)+f(i-1,j-1)-t;
}
}
*/

int main()
{
int n=1,i,j,k;
scanf("%s",S+1);
n=strlen(S+1);
for(i=0;i<=n;i++)
for(j=0;j<=3;j++)
if(j==0||j==i)  F[i][j]=1;
else if(j<i)
{
F[i][j] = F[i-1][j]+F[i-1][j-1];
for(k=i-1;k>=i-j;k--)
if(S[k]==S[i])
{
F[i][j] -= F[k-1][j+k-i];
break;
}
}
printf("%lld\n",F
[0]+F
[1]+F
[2]+F
[3]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐