Zut_round 8(多维dp1)

A - 编辑距离 裸题
思考:这题写过动态规划,先对dp[i][0]和dp[0][j]都初始化为1,dp分为等于的时候,和不等于的时候。具体分析代码里面有。
代码:

#include
#include
#include
using namespace std;
const int maxn=1010;
int dp[maxn][maxn],len1,len2;
char s1[maxn],s2[maxn];
void DP()
{
    for(int i=1;i<=len1;i++)
        dp[i][0]=i;
    for(int i=1;i<=len2;i++)
        dp[0][i]=i;
    for(int i=1;i<=len1;i++)
        for(int j=1;j<=len2;j++)
    {
        if(s1[i]==s2[j])
        dp[i][j]=dp[i-1][j-1];//相同的话就不用操作。
    else dp[i][j]=min(dp[i-1][j-1]+1,min(dp[i][j-1]+1,dp[i-1][j]+1));
    //不同的话就要操作,这里有三种操作替换、插入和删除。
   //分别是dp[i-1][j-1]+1、dp[i][j-1]+1和dp[i-1[[j]+1。
    //这三个应该跟据dp关系写,容易理解。
    }
}
int main()
{
    cin>>s1+1;
    cin>>s2+1;
    len1=strlen(s1+1);
    len2=strlen(s2+1);
    DP();
    cout<<dp[len1][len2];
    return 0;
}


**B - LCS 裸题 **
**思考:**这题在测试之前做过,思路我写在代码里面了。

#include
#include
#include
using namespace std;
char s1[1010],s2[1010],c[1010];
int dp[1010][1010],len1,len2;
void DP(){
    for(int i=1;i<=len1;i++)
        for(int j=1;j<=len2;j++)
    {
        if(s1[i]==s2[j])
            dp[i][j]=dp[i-1][j-1]+1;
        else
            dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    }


}
void out(){
    int k=0;
    int x=len1,y=len2;
    while(x!=0&&y!=0){
        if(s1[x]==s2[y]){
            c[++k]=s1[x--];
            y--;//需要注意.
            //为什么y也需要减呢,举个反例:s1:aaa,s2:a;思考一下就明白了。
        }
        else if(dp[x][y-1]>dp[x-1][y])
               y--;
        else if(dp[x][y-1]<=dp[x-1][y])//这个也让我迷惑了很长时间。
        //当时我在想,当等于的时候应该可以直接x--同时y--,这里有个例子否定
        //这个想法,:s1:abcicba  s2:abdkscab,这个例子最长公共子序列有两个abcb和abca,因此在
        //同时x--和y--的时候,正好讲个子序列最后的都毁了变成了abc.
        //还有一个说明这种想法不行:在找子序列的时候是通过推dp[][]的方法反推出来的,
        //因此应该像推dp[][]的时候一样,x和y,一个一个遍不能一起变。
            x--;
    }
    for(int i=k;i>=1;i--)
        cout<<c[i];
}
int main()
{
    cin>>s1+1;
    cin>>s2+1;
    len1=strlen(s1+1);
    len2=strlen(s2+1);
    DP();
    out();



    return 0;
}

**E-繁荣的地段 **
除Nian外,还有一个名为Sui的守护程序,该守护程序使孩子们感到恐惧并使他们生病。父母给孩子裹着红色小包的钱,把它们放在枕头下,这样,当隋试图接近他们时,里面的仙女会赶走他们。

Big Banban犹豫要捐出多少钱。他认为循环很幸运,因为循环象征着团结与和谐。

他想找到一个不大于10 18的正整数n,以便在n的十进制表示中恰好有k个循环,或者确定不存在这样的n个。

甲环是通过写入阿拉伯数字在数字十进制表示线所包围的平面区域。例如,有一个循环中的数字4,在两个环8和在没有循环5。有关所有确切形式,请参考下图。

输入值
第一和唯一的行包含一个整数ķ(1≤  ķ  ≤10 6) -环的期望数量。

输出量
输出一个整数-如果不存在这样的n,则输出-1;否则输出任何这样的n。在后一种情况下,您的输出应为不超过10 18的正十进制整数。

例子
输入值
2
输出量
462
输入值
6
输出量
8080
思考这题应该是最简单的了吧,但是我测试的时候越写脑子越紧,思路打不开,这题1e18,我想成了十八位数,哎,没想100即1e2是个三位数,就出了bug没写出来。
代码:

#include
using namespace std;
int main()
{
    int k;
    cin>>k;
    int t1=k/2;
    int t2=k%2;
    if(t1+t2<=18){
        if(t2==1){
            cout<<"4";
        }
        for(int i=1;i<=t1;i++)
            cout<<"8";
        }else{
        cout<<"-1";
        }
        return 0;
}

F-兼容对
念是生活在海洋深处的怪物。每年一次,它出现在土地上,吞噬牲畜甚至人类。为了使怪物远离,人们在村庄中充斥着红色,灯光和刺耳的噪音,所有这些都会使怪物吓跑。

小汤米有n盏灯笼,大版板有m盏灯笼。汤米的灯笼分别具有亮度a 1,  a 2,…,  a n和班班的灯笼分别具有亮度b 1,  b 2,…,  b m。

Tommy打算隐藏他的一个灯笼,然后Banban挑选Tommy的一个非隐藏灯笼和一个他自己的灯笼组成一对。该对的亮度将是两个灯笼的亮度的乘积。

Tommy希望使产品尽可能小,而Banban试图使产品尽可能大。

如果两者都选择最佳,则会要求您找到所选对的亮度。

输入值
第一行包含两个空间分开的整数Ñ和米(2≤  Ñ,  米  ≤50)。

第二行包含n个以空格分隔的整数a 1,  a 2,…,  a n。

第三行包含m个以空格分隔的整数b 1,  b 2,…,  b m。

所有整数的范围是 -10 9到10 9。

输出量
打印一个整数-所选对的亮度。

例子
输入值
2 2
20 18
2 14
输出量
252
输入值
5 3
-1 0 1 2 3
-1 0 1
输出量
2
注意
在第一个示例中,汤米将隐藏20,班班将从汤米中选择18,并从他自己中选择14。

在第二个示例中,汤米将隐藏3,班班将从汤米中选择2,并从他自己中选择1。
思考:这题我一开始想的是将两个数列直接sort再用a[n-1]*b[n],wa了,没仔细思考数的范围有负数,负负得正啊,这样当然是不行的,只能暴力,求出第二个最大值,但在暴力的时候也是有细节的,①不能用二维数组保存乘积值再求第二个最大值(没方法呀)。②暴力的时候外面套for(int i=1;i<=n;i++),里面套b的循环,这是因为对于最大值和第二大的值b数列这个数可以重复,而a数列中的数不能重复,因为a中的那个数是要被藏起来的。③将求二维第二大的值转换为一唯的,求每一个a[i]相乘的最大值,是可以的因为我们只求一个数即第二大的值,将a循环在外面,就不用考虑重复了。
代码:

#include
#include
using namespace std;
typedef long long ll;
ll a[55],b[55],c[55];
const ll MAX=1e18;
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=m;i++)cin>>b[i];
    for(int i=1;i<=n;i++){
            c[i]=-MAX;
        for(int j=1;j<=m;j++)
         {
            c[i]=max(c[i],a[i]*b[j]);
         }
    }
    sort(c+1,c+1+n);
    cout<<c[n-1];
    return 0;
}

你可能感兴趣的:(Zut_round 8(多维dp1))