社区
Java SE
帖子详情
一个算法问题
volkia
2004-12-04 12:45:46
给定一个数字字符串(长度为N位),如819(长为三位),现给K个乘号,比如一个*
试问,在不改变数字字符串的顺序前提下,这些乘号放在哪些地方,得到的积最大.
如 819,一个 *, 则结果应为:
8*19 =152
81*9 =729
所以,结果为 81*9=729
现在假设N不超过40,K不超过10,请给出该算法.
...全文
356
33
打赏
收藏
一个算法问题
给定一个数字字符串(长度为N位),如819(长为三位),现给K个乘号,比如一个* 试问,在不改变数字字符串的顺序前提下,这些乘号放在哪些地方,得到的积最大. 如 819,一个 *, 则结果应为: 8*19 =152 81*9 =729 所以,结果为 81*9=729 现在假设N不超过40,K不超过10,请给出该算法.
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
33 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
volkia
2005-01-06
打赏
举报
回复
有几天没来了哈,我也正在找高人求解,不知会不会有结果.
findingnimo
2004-12-27
打赏
举报
回复
呵呵,本来我想证明你的算法是对的,可到最后竟然找了一个反例出来,应该是我对不起吧:)
你试着把它表示成数学公式,然后对这个公式求最大值。
volkia
2004-12-25
打赏
举报
回复
to findingnimo():
对不起,看来算法真的是有点问题!
不过,难道真的非暴力不可吗?
递归效率也不太高,还有没有其它办法?我可以重新开贴再给分哈.
findingnimo
2004-12-23
打赏
举报
回复
最大值: 555*555*555 = 170953875
你算得结果:5555*55*555 = 169566375
findingnimo
2004-12-23
打赏
举报
回复
你这个算法思想有一点问题,没有办法证明你的算法的正确性。
你试一下:
数字串:555555555 乘号个数:2
volkia
2004-12-22
打赏
举报
回复
import java.io.*;
public class MkMethod
{
private static double maxValue;
private static String str;
private static int multiNum;
private static ComputeNode cn;
private static int nodeNum;
MkMethod(String s,int m)
{
str=s;
multiNum=m;
maxValue=0.0;
nodeNum=1;
//cn是头结点,其字符串无用,"10"是个任意串
cn=new ComputeNode("10");
//第一个结点是串s
cn.setNext(new ComputeNode(s));
}
//返回拆分结点(字符串)p得到的整个乘积
public double getSpecMax(ComputeNode p)
{
double max=1.0;
ComputeNode next=this.cn.getNext();
for (int i=1;i<=nodeNum;i++)
{
if (next==null) break;
if (next!=p)
{
//如果不是结点p,则乘积为原串的值
max=max*next.getValue();
}
else
{
//如果是结点p,则乘积项为该串拆分后的乘积
max=max*next.getMax();
}
next=next.getNext();
}
return max;
}
//主要方法,计算每个乘号的位置和此时乘积的值
public void findMaxMultiValue()
{
ComputeNode next,current;
//一共有multiNum个乘号
for (int i=1;i<=multiNum;i++)
{
next=this.cn.getNext();
double max=0.0;
//计算每个结点的拆分结果
for (int j=1;j<=nodeNum;j++)
{
if (next==null) break;
//该结点是新结点(左子串为空,且长度不为1,且最大值不为0),则拆分
if (next.getLeftStr()==null && next.getString().length()>1 && next.getMax()<0.1)
{
next.splitStr();
}
next=next.getNext();
}
//next作为循环计算各结点最大值而设
//current指向要拆分结点的前驱结点
next=this.cn;
current=next;
maxValue=0.0;
for (int j=1;j<=nodeNum && next.getNext()!=null;j++)
{
//如果该串只有一位数字,则跳过该结点
if (next.getNext().getLeftStr()==null)
{
next=next.getNext();
continue;
}
//计算该结点拆分后的最大乘积
max=getSpecMax(next.getNext());
//如果比前一结点的最大乘积大
if (max>maxValue)
{
maxValue=max;
current=next;
}
next=next.getNext();
}
//current已指向当前应拆分结点的前驱结点
//取得其第一子串和第二子串分别构建两个新的结点left和right
ComputeNode left=new ComputeNode(current.getNext().getLeftStr());
ComputeNode right=new ComputeNode(current.getNext().getRightStr());
//将right接在left后面,并把left接到current后面
//即,使用left和right替换原来的结点
left.setNext(right);
right.setNext(current.getNext().getNext());
current.setNext(left);
//结点数加1
nodeNum++;
}
}
//将整个字符串结点输出
public String toString()
{
ComputeNode c=cn.getNext();
String s="";
for (int i=0;i<nodeNum && c!=null;i++)
{
if (i==0)
s+=c.getString();
else
s+="*"+c.getString();
c=c.getNext();
}
return s;
}
//返回整个乘积串的值
public double getMaxValue()
{
return maxValue;
}
public static void main(String[] args)
{
String s;
int n;
if(args.length != 2)
{
System.out.println("必须指定两个整型参数,第一个为数字字符串,第二为在其中插入乘号的个数.");
return;
}
s=args[0];
n=Integer.parseInt(args[1]);
if (n>=s.length())
{
System.out.println("乘号个数必须小于串的长度!");
return;
}
long x=System.currentTimeMillis();
MkMethod mm=new MkMethod(s,n);
mm.findMaxMultiValue();
System.out.print(mm.toString());
System.out.println(" ="+mm.getMaxValue());
long y=System.currentTimeMillis();
System.out.println("共耗时 "+(y-x)+" 微秒.");
}
}
volkia
2004-12-22
打赏
举报
回复
代码分开贴: (因为考虑到可读性和规范,所以可能会很长)
/**
* MkMethod.java
* (c)Copyright MKing,2004
*/
class ComputeNode
{
String str=null; //原串
//拆分后的字串,如果只有一个数字,则子串全为null
String subStr1=null,subStr2=null;
double value=0.0; //原串的值
double curMax=0.0; //拆分后的乘积
ComputeNode next; //下一结点
//用一个字符串构造一个结点
public ComputeNode(String s)
{
str=new String(s);
value=Double.parseDouble(s);
curMax=0.0;
next=null;
subStr1=null;
subStr2=null;
}
//拆分该结点的字符串为两个字符串,使乘积最大,最大乘积存在curMax中
public boolean splitStr()
{
int pos=0;
double max=0.0;
//如果字符串长1,即只有一个数字,则值为该值,并返回false
if (str.length()==1)
{
curMax=value;
return false;
}
//尝试乘号的可能位置
for (int i=1;i<str.length();i++)
{
String s1,s2;
s1=str.substring(0,i);
s2=str.substring(i);
double d1=Double.parseDouble(s1);
double d2=Double.parseDouble(s2)*d1;
if (d2>max)
{
max=d2;
pos=i;
}
}
//得到最大乘积和乘号位置,则子串可确定
curMax=max;
subStr1=str.substring(0,pos);
subStr2=str.substring(pos);
return true;
}
public String getString()
{
return str;
}
public String getLeftStr()
{
return subStr1;
}
public String getRightStr()
{
return subStr2;
}
public double getMax()
{
return curMax;
}
public double getValue()
{
return value;
}
public ComputeNode getNext()
{
return next;
}
public void setNext(ComputeNode c)
{
next=c;
}
}
volkia
2004-12-22
打赏
举报
回复
呵呵,谢谢大家!谢谢"大花猫"!
感觉求组合数太暴力了点 :)
我是这样算的:
比如 3345096 (长度为N) ,乘号个数为2
则,先求第一个乘号,很显然,应该有N-1种可能,求出最大的很简单
即将原串分成 33450(s1) * 96(s2)
再比较在s1中按上述方法插入一下乘号的积与96
和
33450 与在s2中按上述方法插入一个乘号后的积的大小,可确定第二个乘号
同理,可以确定余下乘号.
如果考虑封装一种结构(类)来实现,则每个子串中的乘号位置只需要计算一次,只有子串被拆分以后才需要重新计算乘号位置.因此时间复杂度并不会太大.
不过,有个问题,如果串的长度超出了长整数(long)表示的范围,则需要自定义数字字符串的乘积和大小比较方法,这个要难些.
cxz7531
2004-12-16
打赏
举报
回复
上面的有些缺点,出现了重复搜索的现象,再完善一下
public class MaxMulValue {
private static String asscat=""; //其值最大的组合方式
private static int ncount=0; //总的组合个数
public static void main(String[] args) {
String numstr="67545656975666"; //参照的数字字符串
int mulcount=8; //乘号个数
long nvalue=getMaxZuhe(numstr,mulcount);
System.out.println("---------------------");
System.out.println("参考字符串为 "+numstr+" 乘号个数为 "+mulcount);
System.out.println("一共"+ncount+"种组合 ");
System.out.println("最大值为 "+nvalue);
System.out.println("组合方式为 "+asscat);
System.out.println("---------------------");
}
public static long getMaxZuhe(String numstr ,int mulcount){
/*
参数含义
numstr 参照的数字字符串
mulcount 乘号个数
返回值 返回最大值
组合方式和总的组合个数在类成员asscat和ncount中
*/
int m=numstr.length();
int []ns=new int[m-1];
for(int j=0;j<m-1;j++){
ns[j]=(int)Math.round(Math.pow(2,j));
}
int nlim=(int)Math.round(Math.pow(2,m-1));
long nvalue=-1;
for(int i=0;i<nlim;i++){
int ntotal=0;
int []kk=new int[mulcount];
int kksign=0;
for(int k=0;k<m-1;k++){
if((i & ns[k])>0 ) {
ntotal++;
if(ntotal>mulcount) break ;
kk[kksign]=k;
kksign++;
}
}
if(ntotal==mulcount){
String s="";
long v=1;
for(int np=0;np<mulcount;np++){
if(np==0){
String t=numstr.substring(0,kk[np]+1);
s=s+t+"*";
v=v*Long.parseLong(t);
}else if(np==mulcount-1){
String t1= numstr.substring(kk[np-1]+1,kk[np]+1);
String t2=numstr.substring(kk[np]+1,numstr.length());
s=s+t1+"*"+t2;
v=v*Long.parseLong(t1)*Long.parseLong(t2);
}else{
String t=numstr.substring(kk[np-1]+1,kk[np]+1);
s=s+t+"*";
v=v*Long.parseLong(t);
}
}
if(nvalue<v) {
nvalue=v;
asscat=s;
}
ncount++;
System.out.println("第"+ncount+"种组合:"+s+"="+v);
}
}
return nvalue;
}
}
输出结果是:
.............................
第1282种组合:6*754565*6*9*7*5*6*6*6=1848261693600
第1283种组合:67*54565*6*9*7*5*6*6*6=1492466245200
第1284种组合:675*4565*6*9*7*5*6*6*6=1257940530000
第1285种组合:6754*565*6*9*7*5*6*6*6=1557847922400
第1286种组合:67545*65*6*9*7*5*6*6*6=1792347102000
第1287种组合:675456*5*6*9*7*5*6*6*6=1378740787200
---------------------
参考字符串为 67545656975666 乘号个数为 8
一共1287种组合
最大值为 2574142740000
组合方式为 6*7545*65*6*9*75*6*6*6
---------------------
wqqissc
2004-12-16
打赏
举报
回复
楼上那样的方法,恐怕是个指数级的复杂度了。呵呵,严格的说,这不是算法,是蛮力
cxz7531
2004-12-16
打赏
举报
回复
修改后的程序输出结果是:
....................
第2375种组合:67*54*5*6*5*6*9*7*5666=1162326639600
第2376种组合:6*7*54*5*6*5*6*9*75666=1390044952800
第2377种组合:675*4*5*6*5*6*9*7*5666=867407940000
第2378种组合:6*75*4*5*6*5*6*9*75666=1103210280000
第2379种组合:67*5*4*5*6*5*6*9*75666=821278764000
第2380种组合:6*7*5*4*5*6*5*6*975666=737603496000
---------------------
参考字符串为 67545656975666 乘号个数为 8
一共2380种组合
最大值为 2574142740000
组合方式为 6*7545*65*6*9*75*6*6*6
---------------------
qinliu0425
2004-12-16
打赏
举报
回复
这个很高深的,弄不懂
cxz7531
2004-12-16
打赏
举报
回复
刚才的程序忘了考虑超出Integer范围的问题,现在用Long代替Integer,就对了
/**
* Created on 2004-12-16
* HOPETECH
*
*
* ====================================================================
*
* The HOPETECH License, Version 1.0
*
* Copyright (c) 1999-2004 The HOPETECH Foundation. All rights
* reserved.
*/
/**
* @author tc jinsq
* @version Revision: 1.0 Date: 2004-12-16
*/
public class MaxMulValue {
private static String asscat=""; //其值最大的组合方式
private static int ncount=0; //总的组合个数
public static void main(String[] args) {
String numstr="67545656975666"; //参照的数字字符串
int mulcount=8; //乘号个数
long nvalue=getMaxZuhe(numstr,mulcount);
System.out.println("---------------------");
System.out.println("参考字符串为 "+numstr+" 乘号个数为 "+mulcount);
System.out.println("一共"+ncount+"种组合 ");
System.out.println("最大值为 "+nvalue);
System.out.println("组合方式为 "+asscat);
System.out.println("---------------------");
}
public static long getMaxZuhe(String numstr ,int mulcount){
/*
参数含义
numstr 参照的数字字符串
mulcount 乘号个数
返回值 返回最大值
组合方式和总的组合个数在类成员asscat和ncount中
*/
int m=numstr.length();
int []ns=new int[m-1];
for(int j=0;j<m-1;j++){
ns[j]=(int)Math.round(Math.pow(2,j));
}
int nlim=(int)Math.round(Math.pow(2,m-1));
long nvalue=-1;
for(int i=0;i<nlim;i++){
int ntotal=0;
int []kk=new int[mulcount];
int kksign=0;
for(int k=0;k<m-1;k++){
if((i & ns[k])>0 ) {
ntotal++;
if(ntotal>mulcount) break;
kk[kksign]=k;
kksign++;
if(ntotal==mulcount){
String s="";
long v=1;
for(int np=0;np<mulcount;np++){
if(np==0){
String t=numstr.substring(0,kk[np]+1);
s=s+t+"*";
v=v*Long.parseLong(t);
}else if(np==mulcount-1){
String t1= numstr.substring(kk[np-1]+1,kk[np]+1);
String t2=numstr.substring(kk[np]+1,numstr.length());
s=s+t1+"*"+t2;
v=v*Long.parseLong(t1)*Long.parseLong(t2);
}else{
String t=numstr.substring(kk[np-1]+1,kk[np]+1);
s=s+t+"*";
v=v*Long.parseLong(t);
}
}
if(nvalue<v) {
nvalue=v;
asscat=s;
}
ncount++;
System.out.println("第"+ncount+"种组合:"+s+"="+v);
}
}
}
}
return nvalue;
}
}
cxz7531
2004-12-16
打赏
举报
回复
输出结果如下:
..................................
第2373种组合:6754*5*6*5*6*9*7*5*666=-375792912
第2374种组合:6*754*5*6*5*6*9*7*5666=1691246752
第2375种组合:67*54*5*6*5*6*9*7*5666=-1609497616
第2376种组合:6*7*54*5*6*5*6*9*75666=-1524451104
第2377种组合:675*4*5*6*5*6*9*7*5666=-175453792
第2378种组合:6*75*4*5*6*5*6*9*75666=-596315072
第2379种组合:67*5*4*5*6*5*6*9*75666=940010464
第2380种组合:6*7*5*4*5*6*5*6*975666=-1130878912
---------------------
参考字符串为 67545656975666 乘号个数为 8
一共2380种组合
最大值为 2147166432
组合方式为 6*7*54*565*69*75*6*6*6
---------------------
cxz7531
2004-12-16
打赏
举报
回复
/**
* Created on 2004-12-16
* HOPETECH
*
*
* ====================================================================
*
* The HOPETECH License, Version 1.0
*
* Copyright (c) 1999-2004 The HOPETECH Foundation. All rights
* reserved.
*/
/**
* @author tc jinsq
* @version Revision: 1.0 Date: 2004-12-16
*/
public class MaxMulValue {
private static String asscat=""; //其值最大的组合方式
private static int ncount=0; //总的组合个数
public static void main(String[] args) {
String numstr="67545656975666"; //参照的数字字符串
int mulcount=8; //乘号个数
int nvalue=getMaxZuhe(numstr,mulcount);
System.out.println("---------------------");
System.out.println("一共"+ncount+"种组合 ");
System.out.println("最大值为 "+nvalue);
System.out.println("组合方式为 "+asscat);
System.out.println("---------------------");
}
public static int getMaxZuhe(String numstr ,int mulcount){
/*
参数含义
numstr 参照的数字字符串
mulcount 乘号个数
返回值 返回最大值
组合方式和总的组合个数在类成员asscat和ncount中
*/
int m=numstr.length();
int []ns=new int[m-1];
for(int j=0;j<m-1;j++){
ns[j]=(int)Math.round(Math.pow(2,j));
}
int nlim=(int)Math.round(Math.pow(2,m-1));
int nvalue=-1;
for(int i=0;i<nlim;i++){
int ntotal=0;
int []kk=new int[mulcount];
int kksign=0;
for(int k=0;k<m-1;k++){
if((i & ns[k])>0 ) {
ntotal++;
if(ntotal>mulcount) break;
kk[kksign]=k;
kksign++;
if(ntotal==mulcount){
String s="";
int v=1;
for(int np=0;np<mulcount;np++){
if(np==0){
String t=numstr.substring(0,kk[np]+1);
s=s+t+"*";
v=v*Integer.parseInt(t);
}else if(np==mulcount-1){
String t1= numstr.substring(kk[np-1]+1,kk[np]+1);
String t2=numstr.substring(kk[np]+1,numstr.length());
s=s+t1+"*"+t2;
v=v*Integer.parseInt(t1)*Integer.parseInt(t2);
}else{
String t=numstr.substring(kk[np-1]+1,kk[np]+1);
s=s+t+"*";
v=v*Integer.parseInt(t);
}
}
if(nvalue<v) {
nvalue=v;
asscat=s;
}
ncount++;
System.out.println("第"+ncount+"种组合:"+s+"="+v);
}
}
}
}
return nvalue;
}
}
EverythingMaster
2004-12-16
打赏
举报
回复
呵呵等着看大花猫的答案了!
cxz7531
2004-12-16
打赏
举报
回复
这是一个排列组合的问题。让我来解决。晚上给你答案
ggokind
2004-12-12
打赏
举报
回复
不好意思,我的方法不可行,太天真了
ggokind
2004-12-12
打赏
举报
回复
我觉得递归完全可以解决:
假设前K-1个*已经按要求插入,现在要插入第K个*。
在被K-1个*所分隔的数字中找到一个最大的数,从中分开就可以了(奇数位的话可以比较一下从中分开两种情况的大小)。
大家共同探讨:)。
volkia
2004-12-12
打赏
举报
回复
先看看,谢谢.
加载更多回复(13)
算法
设计与分析
对每种
算法
设计方法都选取了典型的
问题
说明
算法
设计策略的具体应用,在理论介绍和伪代码基础上,进一步用C++语言实现
算法
,通过代码实现进一步加深对
算法
原理的理解,提高学员的编程能力,同时还会加强作业辅导并...
算法
1.
算法
定义 ...如果
一个
算法
有缺陷,或不适合于某个
问题
,执行这个
算法
将不会解决这个
问题
。不同的
算法
可能用不同的时间、空间或效率来完成同样的任务。
一个
算法
的优劣可以用空间复杂度与时间复杂度来衡量。
优化
算法
——模拟退火
算法
最后的结果模拟退火
算法
原理爬山法是一种贪婪的方法,对于
一个
优化
问题
,其大致图像(图像地址)如下图所示: 其目标是要找到函数的最大值,若初始化时,初始点的位置在CC处,则会寻找到附近的局部最大值AA点处,...
如何使用
算法
解决
问题
文章目录如何使用
算法
解决
问题
算法
解决
问题
思路调度的
问题
投资
问题
...这里举
一个
例子: 调度的
问题
从这
问题
中,通过直觉感觉到耗时少的放到前面可以达到最优,这样是一种贪心的策略 然后,我们可以找到规律,...
利用遗传
算法
求解TSP
问题
旅行商
问题
是图论中的
一个
著名
问题
。 假设有
一个
旅行商人要拜访N个城市,要求他从
一个
城市出发,每个城市最多拜访一次,最后要回到出发的城市,保证所选择的路径长度最短。 二、
算法
描述 (一)
算法
简介 遗传...
Java SE
62,614
社区成员
307,327
社区内容
发帖
与我相关
我的任务
Java SE
Java 2 Standard Edition
复制链接
扫一扫
分享
社区描述
Java 2 Standard Edition
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章