练习7

问题 B: 习题6-12 解密


时间限制: 1 Sec  内存限制: 12 MB



提交: 50  解决: 31  外部导入


提交状态讨论版 
  



题目描述 


有一行电文,已按如下规律译成密码: 

A-->Z        a-->z 

B-->Y        b-->y 

C-->X        c-->x 

......          ...... 

即第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求根据密码译回原文,并输出。 



输入 

输入一行密文 



输出 

解密后的原文,单独占一行。 



样例输入 Copy 

ZYX123zyx




样例输出 Copy 

ABC123abc
int main()
{
    string s;
    while(cin>>s)
    {
        int len,i;
        len=s.size();
        for(i=0;i<len;i++)
        {
            if(s[i]=='Z')
            {
                s[i]='A';
            }
            else if(s[i]=='z')
            {
                s[i]='a';
            }
            else if(s[i]>='B'&&s[i]<='Y')
            {
                s[i]=155-s[i];
            }
            else if(s[i]>='b'&&s[i]<='y')
            {
                s[i]=219-s[i];
            }
        }
        cout<<s<<endl;
    }
    return 0;
}

 

问题 C: 数字三角形之备忘录法


时间限制: 1 Sec  内存限制: 128 MB



提交: 2  解决: 0  201501010119


提交状态讨论版 
  



题目描述 

如下图所示的数字三角形,从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。编写一个程序求出最佳路径上的数字之和。 【使用备忘录法实现】


         7 


       3   8 


     8   1   2 


   2   7   4   4 


4    5   2   6   5 






输入 

多组样例输入,每组第一行输入三角形的层数n,接下来n行输入三角形。    



输出 

输出最佳路径上的数字之和。    



样例输入 Copy 

2
1
1 2
3
1
1 2
1 2 3




样例输出 Copy 

3
6



提示 

路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。    
using namespace std;
int a[105][105],p[105][105],n;

int s(int i,int j)
{
    if(p[i][j]>=0)   //如果计算过了
        return p[i][j];
    if(i==n+1)   //p虽然是第i行,但是最下面一行已经算过了,所以这是结束递归的条件
        return 0;
    else
        return p[i][j]=a[i][j]+max(s(i+1,j),s(i+1,j+1));   //规律,a[i][j](处于i,j位置的数组元素a,)加上它正下方的元素和斜下方的元素取最大=》最优子结构,从一开始就取最大值
}

int main()
{
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)   //注意输入的数组为三角形状,所以不要搞混i,j的取值
            for(int j=1;j<=i;j++)
            cin>>a[i][j];
        memset(p,-1,sizeof(p));   //把p置为-1
        s(1,1);   //下标从1开始
        cout<<p[1][1]<<endl;
    }
    return 0;
}

以上为备忘录法;

p数组用来记录是否算过路径;因为最初的想法就是从最上部一直递归到最下面,但是这样时间复杂度很大,所以用一个数组来存是否算过这条路;

递归从(1,1)开始,但是一直递归到最下面那一层,当递归结束的时候开始返回上一层(计算结果),但是在返回上一层的时候很多数我们是重复计算过的,所以我们需要一个数组来备忘 记录我们是否算过这个数,

 

 

动态规划法

从底向上找最优解

int a[105][105],p[105][105],n;

int s()
{
    for(int j=1;j<=n;j++)
        p[n][j]=a[n][j];  //把a最后一行的值给p的最后一行
    for(int i=n-1;i>=1;i--)   //自底向上
        for(int j=1;j<=i;j++)
            p[i][j]=a[i][j]+max(p[i+1][j],p[i+1][j+1]);   //其实从备忘录法已经可以猜到dp规律了
    return 0;
}

int main()
{
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=i;j++)
            cin>>a[i][j];
        memset(p,-1,sizeof(p));
        s();
        cout<<p[1][1]<<endl;
    }
    return 0;
}

 

posted @ 2019-04-15 22:55  RAIN-code  阅读(295)  评论(0编辑  收藏  举报