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;
}