Week10 作业

A - 签到题

在这里插入图片描述
解题过程
使用递归,当达到要求数值时返回操作次数,当n>m时说明转化不了输出-1.

#include <iostream>
using namespace std;
int f=0,c=0;
void  dfs(int n,int m,int count)
{ if(n>m||f==1)
  return ;
  if(n==m)
  { f=1;
    c=count;
    return;
  	
  }
    dfs(n*2,m,count+1);
  	dfs(n*3,m,count+1);
 } 

int main(int argc, char** argv) {
	int n,m;
	cin>>n>>m;
	 dfs(n,m,0);
	 if(f==0)
	 cout<<-1<<endl;
	 else
	 cout<<c<<endl;
	return 0;
}

B - LIS & LCS

在这里插入图片描述
在这里插入图片描述
解题过程
LIS最长上升子序列,可以使用动态规划思想求解。f[i]为以ai为末尾的最长上升子序列长度,一开始视所有序列只包含ai一个数所以f[i]初始化为1,最大的f[i]就是本题的答案。在满足序列上升的同时保证 dp[ i ] 尽可能大,当a[j]<a[i]时说明a[i]末尾的序列可以加入a[j]即f[i]=max(f[i],f[j]+1)。
LCS最长公共子序列,也是动态规划。dp[i][j] 为序列A1—Ai和B1—Bj的LCS长度,对两个序列进行遍历,如果Ai=Bj,则dp[i+1][j+1]就是dp[i][j]+1,即加入了一个新数,如果不等于则dp[i+1][j+1]就是g[ i ] [j-1]和g[i-1][j]中的最大值,即A1—Ai与B1—Bj-1和A1—Ai-1与B1—Bj的最长公共子序列的较长者。

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int a[5020];
int b[5020];
int f[5020],dp[5020][5020];
int n,m,ansa,ans;
void maxlis()
{  for(int i=1;i<=n;i++)
  { for(int j=1;j<=i;j++)
    {if(a[j]<a[i])
     f[i]=max(f[i],f[j]+1);	
	}
	if(f[i]>ansa)
	ansa=f[i];
   }  
}

void maxlcs()
{  for(int i=1;i<=n;i++)
  { for(int j=1;j<=m;j++)
    {if(b[j]==a[i])
     dp[i][j]=dp[i-1][j-1]+1;
	 else
	 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);	
	}
  	
  }
  ans=dp[n][m];
}

int main(int argc, char** argv) {
	memset(f, 0, sizeof(f)); 
	memset(dp, 0, sizeof(dp)); 
	ansa=0;ans=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		f[i]=1;
	}
	
	for(int i=1;i<=m;i++)
	cin>>b[i];
	maxlis();
	maxlcs();
	cout<<ansa<<" "<<ans;  
	
}

C - 拿数问题 II

在这里插入图片描述

Input
2
1 2
Output
2
Input
3
1 2 3
Output
4
Input
9
1 2 1 3 2 2 2 2 3
Output
10

解题过程
需要求出最大分值,用一个数组b统计数组a中每个数出现的个数,dp[i]指拿小于等于i分的数中能拿到的最大分数。拿了i后,i+1与i-1不能再被拿所以dp[i]=max(dp[i-2]+b[i]*i,dp[i-1]),答案为dp数组中最大的数。

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long a[100020];
long long b[100020],dp[100020];
long long n,ans=0;
long long minn=100020,maxn=-1;
void dpp()
{ 
	for(long long i=minn;i<=a[n];i++)
	{   if(i-2>0)
	    dp[i]=max(dp[i-2]+b[i]*i,dp[i-1]);
	    else
	    dp[i]=max(dp[0]+b[i]*i,dp[i-1]);
	    ans=max(ans,dp[i]);
	}
}

int main(int argc, char** argv) {
	memset(b, 0, sizeof(b)); 
	memset(dp, 0, sizeof(b));
	ans=0;
	cin>>n;
	for(long long i=1;i<=n;i++)
	{
		cin>>a[i];
		b[a[i]]++;
		minn=min(a[i],minn);
	}
	sort(a+1,a+1+n);
	dpp();
	cout<<ans;  
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值