2/9 P1018 最大乘积

蒻蒟被困一个上午呜呜呜
先放个链接https://www.luogu.com.cn/problem/P1018

DS大爹帮忙弄出来的AC代码
#include <bits/stdc++.h>
using namespace std;
#define LL long long int
const int MAX=55,MOD=10;
int n,k;
struct HP{
	int p[55],len;
	HP(){
		memset(p,0,sizeof(p));
		len=0;
	}
	void print(){
		for(int i=len;i>=1;i--) cout<<p[i];
	}
	void read(){
		len=n;
		char ch;
		int cnt=0;
		while(cnt<n){//因为有回车,所以要检查是否为数字!!!
			ch=getchar();
			if(isdigit(ch)){
				p[len-cnt]=ch-'0';
				cnt++;
			}
		}
	}
}dp[50][10];
HP operator*(const HP &a,const HP &b){
	HP c;
	c.len=a.len+b.len;//乘积的位数为两个乘数位数相加
	memset(c.p,0,sizeof(c.p));
	for(int i=1;i<=a.len;i++){
		for(int j=1;j<=b.len;j++){
			c.p[i+j-1]+=a.p[i]*b.p[j];//乘积引索为i+j-1
		}
	}
	for(int i=1;i<=c.len;i++){
		c.p[i+1]+=c.p[i]/MOD;
		c.p[i]%=MOD;
	}
	while(c.p[c.len+1]>0){
		c.len++;
		c.p[c.len+1]+=c.p[c.len]/MOD;
		c.p[c.len]%=MOD;
	}
	while(c.p[c.len]==0&&c.len>0) c.len--;//检查是否多(c.len>0)出来空位数(c.p[c.len]==0)!!!
	if(c.len==0){//检查是否为0!!!
		c.len=1;
		c.p[1]=0;
	}
	return c;
}
HP max(const HP &a,const HP &b){
	if(a.len>b.len) return a;
	else if(a.len<b.len) return b;
	for(int i=a.len;i>=1;i--){
		if(a.p[i]>b.p[i]) return a;
		else if(a.p[i]<b.p[i]) return b;
	}
	return a;
}
HP sl(const HP &a,int l,int r){
	HP b;
	b.len=r-l+1;
	for(int i=1;i<=b.len;i++){
		b.p[b.len-i+1]=a.p[a.len-i-l+2];
        //因为HP是倒序的,所以复制的时候  都要!! 都要!! 使用倒序引索!!!
        //从 1 开始倒序,引索为len-i+1,因为i是要的那个数,减的时候去掉了,所以要加 1 加回来
        //从第 p 个开始倒序,引索为 len-(p-1)-i+1 ,同理,第 p 个数开始,但是-  p 的时候去掉 p 了,所以要少减去一个 p 
	}
	return b;
}
int main()
{
	cin>>n>>k;
	HP s;
	s.read();
	for(int i=1;i<=n;i++)
	{
		dp[i][0]=sl(s,1,i);
	}
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=min(i-1,k);j++)
		{
			for(int m=j;m<i;m++)
			{
				dp[i][j]=max(dp[i][j],dp[m][j-1]*sl(s,m+1,i));
                        //dp[i][j]为前i个数放j个*的最大乘积,那它如何确定呢?
                        //在前面i个数中,最多可放i-1个*,且不超过k
                        //dp[i][j]怎么来的?前一步不就是确认最后一个*放哪吗!
                        //那最后一个*能放哪里呢?
                        //显然,放最后一个*前,已经放了j-1个*
                        //但是我们不知道它们都放在哪里才是最优解该放的地方啊!
                        //那就遍历!
                        //我们设最后一个*放在序号为m的数字之后
                        //那是不是,dp[i][j]就该是dp[m][j-1]* m后面那个数字?
                        //m可以从j一直到i-1
                        //此时,胜利的道路已然展开!
                        //dp[i][j]就等于max{dp[m][j-1]*num(m+1,i)}!!!
			}
		}
	}
	dp[n][k].print();
	return 0;
}
posted @   石磨豆浆  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示