zoukankan      html  css  js  c++  java
  • Luogu

    题解:P1018【乘积最大】


    前言:

    这题的题解里好多人都用的动态规划,我一个蒟蒻居然用暴力全排列AC了。。。

    .

    思路:

    • 利用一个b数组标记每一位之间是否分割。
    • 利用STL里的 next_permutation 求出b的各种排列(即暴力枚举每种情况)。
    • 由于本题数据规模大,所以要使用高精度计算每种分割的最后结果,并找出最大。

    .

    next_permutation函数:

    即STL里的求全排列函数,所求的数组必须是升序,否则将无法求出全部的排列方式(这和它生成群排列的方式有关),next_permutation正常和sort一样,有2个参数,分别是数组的首地址和尾地址,并返回一个bool量,即能否求出下一个全排列,可以的话返回true,并将指定数组变为下一个排列方式,如1 2 3的下一个排列方式就是 1 3 2。


    上代码:

    #include<algorithm> //使用next_permutation需要调用的头文件
    #include<cstdio>  //c语言读入输出
    #include<cstring>  //处理高精度字符串时需要用到
    
    using namespace std;
    
    struct BigN{  //高精度(即大整数)运算
    	int num[1001]={0},len;
    	BigN(char s[])  //构造函数,用于给新定义的大整数赋值
    	{
    		len=strlen(s);
    		for(int i=len-1;i>=0;i--)
    			num[i]=s[len-i-1]-'0';
    	}
    	void clean()  //用于清零
    	{
    		memset(num,0,sizeof(num));
    	}
    	void f(int n)  //将一个普通整数压到大整数的开头,这个在后面分割每一位时会用到
    	{
    		for(int i=len;i>0;i--)
    			num[i]=num[i-1];
    		len++;
    		num[0]=n;
    	}
    	void cheng(BigN n)//高精度乘法,这里就不过多解释了,有疑问可以前往 P1303 了解更多
    	{
    		BigN c("0");
    		int s=0,g=0;
    		for(int i=0;i<=len;i++)
    			for(int j=0;j<=n.len;j++)
    			{
    				int w=i+j;
    				s=num[i]*n.num[j];
    				c.num[w]+=s%10;
    				c.num[w+1]+=s/10+c.num[w]/10;
    				c.num[w]%=10;
    			}
    		c.len=len+n.len;
    		while(c.num[c.len]==0&&c.len>=0)c.len--;
    		fz(c);
    	}
    	void fz(BigN n) //将一个大整数赋值给例外一个大整数,相当于'='
    	{
    		len=n.len;
    		for(int i=0;i<=n.len;i++)
    			num[i]=n.num[i];
    	}
    	bool bj(BigN n)  //判断两个大整数的大小,用于找出最大结果
    	{
    		if(len>n.len)
    			return 1;
    		else if(len<n.len)
    			return 0;
    		else
    		{
    			for(int i=len;i>=0;i--)
    				if(num[i]<n.num[i])
    					return 0;
    				else if(num[i]>n.num[i])
    					return 1;
    			return -1;
    		}
    	}
    	void out() //输出
    	{
    		for(int i=len;i>=0;i--)
    			printf("%d",num[i]);
    	}
    };
    
    int n,k,sum[55],b[55],i,j; //常规定义,不多做解释
    BigN mmax("0");
    
    int main()
    {
        char s[101];  //s用于读入一个大整数
        scanf("%d%d%s",&n,&k,&s);
        for(i=0;i<strlen(s);i++)  //在sum中备份一份原数
            sum[i]=s[i]-'0';
        for(i=n-2;i>=(n-k)-1;i--)  //将b数组中的后k个数赋1,因为使用next_permutation需要让数组升序,否则可能无法找出所有排列方式
            b[i]=1;
        do{
            BigN temp("0"),all("1");//temp用于存放分割后的每一节,all用于计算每种排列方式的结果
            i=0;
            while(i<n)//分割
            {
                if(i!=0)
                    if(b[i-1]==1)//如果b[i-1]为1,那么就要在这一位加上一个乘号,即将原数分割
                        all.cheng(temp),temp.clean();//总数乘上分割后的每一位,并将temp清空,用于储存下一节.
                temp.f(sum[i]),i++; //将原数的下一位压到temp的最前面
            }
            all.cheng(temp);//由于temp还没有乘all就退出循环,所以要再乘一次
            if(mmax.bj(all)==0)//如果这种排列顺序的结果大于之前最大的结果,刷新最大结果
            	mmax.fz(all);
        }while(next_permutation(b,b+n-1));//调用next_permutation
        mmax.out();//输出
        return 0;
    }
    
  • 相关阅读:
    Jasmine入门
    最近面试js部分试题总结
    最近面试前端面试题整理(css部分)
    开发自己的类库
    关于FEer发展方向的思考
    工作那些事(八)工作的目标——《360周鸿祎在新员工入职培训上的讲话》读后感
    工作那些事(七)选择与被选择
    工作那些事(六)谈谈好的编程习惯的好处
    工作那些事(五)谈谈项目资料整理和积累
    工作那些事(四)大公司VS小公司
  • 原文地址:https://www.cnblogs.com/blackbird137/p/13559441.html
Copyright © 2011-2022 走看看