n点游戏

n点游戏

24点游戏是非常经典而简单的小游戏,从一堆扑克牌中抽取4张,向其中添加运算符号并使其运行结果恰等于24,这叫作24点游戏。

现在我们不再是组合24,而是组合出给定的数字n,但要求只可以利用任意多个数字1,并且运算只有加法、乘法和括号。对于给定的数字N,最少需要几个1可以完成

数据输入

输入一个数字N( 1≤N≤5000)

数据输出

输出一个整数,表示仅用加号,乘号和括号能组成等于N所需最少的1的个数

样例1
输入样例
7
输出样例
6
提示
7=(1+1)*(1+1+1)+1
样例2
输入样例
27

输出样例
9

提示
27=(1+1+1)(1+1+1)(1+1+1)

思路

一维的动态规划。
若用f(n)表示计算n所需最少1的个数,对于n=1-5的情形,f(n)=n。
举几个例子,n=6时,6=23,所以f(6)=f(2)+f(3)=5,对于n=9,由于9=33,所以f(9)=f(3)+f(3),要计算f(27),因为27=39,所以f(27)=f(3)+f(9),但计算f(9)还要计算f(9)=f(3)f(3),这样计算的话会出现许多重复,刚才f(9)已经计算出来了,我们可以直接将其保存下来,将f()改为数组d[],从1开始向N计算d[i]的值即可。对于任何数字i>1,d[i]=d[i-1]+1,然后我们再检查是否有两个数字x,y相乘等于i,若有就尝试d[x]+d[y]是否小于当前d[i],若小于就更新d[i]。计算d[i]后依照此法再计算d[i+1],直到计算出d[N].

代码

#include <cstdio>
#include <algorithm>
#define MAXN 5007
using std::min;


int main(void)
{
     int i,j,N;
     int dp[MAXN];
     scanf("%d",&N);
     dp[1]=1;
     for(i=2;i<=N;i++) 
     {
         dp[i]=dp[i-1]+1;//置初始的可能 
         for(j=2;j*j<=i;j++)//开方乘法,这个从质数的考察常见 
         {
             if(i%j==0)//寻找乘法组合 
             {
                 dp[i]=min(dp[i],dp[i/j]+dp[j]);//如果有乘法组合,那么更新 
             }
         }
     }
     printf("%d
",dp[N]);
     return 0;
}
原文地址:https://www.cnblogs.com/lingr7/p/10523744.html