Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 动态规划:计算中间的数字_C++_String_Algorithm_Optimization_Dynamic Programming - Fatal编程技术网

C++ 动态规划:计算中间的数字

C++ 动态规划:计算中间的数字,c++,string,algorithm,optimization,dynamic-programming,C++,String,Algorithm,Optimization,Dynamic Programming,给定两个数字X和Y,它们之间有多少个数字至少有一半的数字相同?例如,1122和4444将起作用,而11234和112233将不起作用 显然,最简单的方法是从X开始,一直递增1到Y,然后检查每个数字,但这太慢了,因为X和Y的边界介于100和10^18之间。我知道这是动态规划的一种形式,我应该用字符串来表示数字,但我不能再进一步了 任何帮助都可以接受。谢谢 显然,考虑范围内的所有数字并不能做到这一点。相反,从生成所需数字的角度考虑。例如,设计一个函数,该函数将生成所有符合条件的数字,给定的长度不超过

给定两个数字
X
Y
,它们之间有多少个数字至少有一半的数字相同?例如,
1122
4444
将起作用,而
11234
112233
将不起作用

显然,最简单的方法是从
X
开始,一直递增1到
Y
,然后检查每个数字,但这太慢了,因为
X
Y
的边界介于
100
10^18
之间。我知道这是动态规划的一种形式,我应该用字符串来表示数字,但我不能再进一步了


任何帮助都可以接受。谢谢

显然,考虑范围内的所有数字并不能做到这一点。相反,从生成所需数字的角度考虑。例如,设计一个函数,该函数将生成所有符合条件的数字,给定的长度不超过以数字为单位的长度

例如,对于5位数字,您希望所有数字至少有三个1或三个2,或者。。。你能一次完成吗,或者你需要把三个1和更多的分开吗

现在你已经考虑过了,想想这个:与其生成所有这些数字,不如数一数。例如,对于三个1和两个其他数字,您有9*9对其他数字(请确保不要重复计算11122之类的数字)。你可以用10种方式排列1,另外两个数字可以互换

请注意,偶数数字的问题有点不同:必须避免对半和对半数字重复计数,例如111222

这能让你动起来吗


对12月3日评论的回应

@bobjoe628:这不是一个完整的算法;相反,这是一个让你开始的建议。是的,你有几个组合问题要处理。至于11122233,我不确定我是否理解您的担忧:与任何此类排列问题一样,您必须处理每个数字与其兄弟姐妹之间的可互换性。有10C5种分配1的方式;在剩余的点中,有5C3种方式分配2;其他两个插槽为3'3。现成的算法(即浏览器搜索)将涵盖这些阴谋

我相信您可以编写一个生成数字的算法:请注意,您只需要一个数字组合,因此按升序生成数字是安全的,正如您所给出的示例:111112233。一旦您生成了这些数字,您的组合代码应该覆盖这些数字的所有唯一排列


最后,请注意,大多数语言都有支持包,可以为您执行排列和组合。

我将在以下几个步骤中向您解释:

第一步:

为了解决
X
Y
之间的这类范围问题,总是通过在
0到X
0到Y-1
之间进行计数,然后减去结果来简化。i、 e.如果您有一个类似于
f(N)
的函数,该函数计算的数字中至少有一半的位数在0和N之间相同,那么您的最终结果是:

f(X) - f(Y-1)
第二步:

接下来我们要计算f(N)。我们将此函数分为两个子函数,一个子函数用于计算与N位数相同的数字的结果(我们称之为f_等于),另一个子函数用于计算小于N位数的合格数字(我们称之为f_小于)。例如,如果N是19354,我们计算0到9999之间的限定数字,然后在另一种方法中计算10000到19354之间的最喜欢的数字,然后我们总结结果。接下来,我将解释如何实现这两种方法

第三步:

这里,我们要计算无f_的方法。你可以通过一些数学来做,但我总是喜欢写一个简单的DP来解决这些任务。我将编写递归函数,不管您是使用memonization还是使用一些循环自下而上(我将留给您作为练习)

long-long f_-less(int curDigit,int favNum,int favNumCountSoFar,int nonavnum,int nonavnumcountsofar,int maxDigit){
if(curDigit==maxDigit){
//对于具有偶数maxDigit的数字,可能有两个最喜欢的数字
//我们应该只数一次,比如522552
if(favNumCountSoFar*2==maxDigit&&favNumCountSoFar==nonavnumcountsofar)返回1;
如果(2*favNumCountSoFar>=maxDigit)返回2;
返回0;
}
长res=0;

对于(inti=(curDigit==0?1:0);这里是一个部分组合答案。我省略了如何使用函数构造完整答案

(请参见此处,以获取具有更详细注释的相同代码:)

固定最左边的数字,
L
,在
R
数字位于
L
右侧的数字中,我们可以通过以下方式计算分配
(N/2)
或更多数字
d
的方式:

Python代码

导入数学、运算符、集合
#假设L至少有一个数字集
#f({'string':'12','digital_frequencies':[0,1,0,0,0,0,0],'num_digital_frequencies':2},6)
def f(左,右):
R=N-len(L['string'])
计数=0
计数=假
对于L[‘数字频率’]中的数字频率:
开始=整数(数学单元(N/2.0))-数字频率
如果开始>R:
持续
对于X范围内的i(开始,R+1):
如果不是(N&1)且未计算在内:
如果L['num_digital_frequencies']=1而不是digital_frequency,且i==N/2:
计数=计数-选择(R,i)
如果L['num_digit_frequencies']=2和digit_frequency而不是任何([x>N/2表示L['digit_frequencies']]中的x)和i+digit_frequency==N/2:
计数=计数-选择(R,i)
计数=Tr
long long f_less(int curDigit, int favNum, int favNumCountSoFar, int nonFavNum, int nonFavNumCountSoFar, int maxDigit){
    if(curDigit == maxDigit ){
        //for numbers with even maxDigit there may be a case when we have 2 favorite numbers
        //and we should count them only once. like 522552
        if(favNumCountSoFar*2 == maxDigit && favNumCountSoFar == nonFavNumCountSoFar) return 1;
        if(2*favNumCountSoFar >= maxDigit) return 2;
        return 0;
    }
    long long res = 0;
    for(int i=(curDigit==0?1:0);i<=9;++i) //skip the leading zero
        if(i==favNum)
            res += f_less(curDigit+1, favNum, favNumCountSoFar + 1, nonFavNum, nonFavNumCountSoFar,maxDigit);
        else
            res += f_less(curDigit+1, favNum, favNumCountSoFar, i, (i==nonFavNum?nonFavNumCountSoFar+1:1),maxDigit);
    return res;
}
long long res = 0;
for(int maxDigit = 1; maxDigit < NUMBER_OF_DIGITS(N); ++maxDigit)
    for(int favNumber = 0; favNumber < 10; ++favNumber)
        res += f_less(0, favNumber, 0, -1, 0, maxDigit);
string s = NUM_TO_STRING(N);
int maxDigit = s.size();
long long f_equal(int curDigit, int favNum, int favNumCountSoFar,int nonFavNum, int nonFavNumCountSoFar, bool isEqual){ //isEqual checks that whether our number is equal to N or it's lesser than it 
    if(curDigit == maxDigit ){
        //for numbers with even maxDigit there may be a case when we have 2 favorite numbers
        //and we should count them only once. like 522552
        if(favNumCountSoFar*2 == maxDigit && favNumCountSoFar == nonFavNumCountSoFar) return 1;
        if(2*favNumCountSoFar >= maxDigit) return 2;
        return 0;
    }
    long long res = 0;
    for(int i=(curDigit==0?1:0);i<=9;++i){ //skip the leading zero
        if(isEqual && i>(s[curDigit]-'0')) break;
        if(i==favNum)
            res += f_equal(curDigit+1, favNum, favNumCountSoFar + 1, nonFavNum, nonFavNumCountSoFar, isEqual && (i==(s[curDigit]-'0')));
        else
            res += f_equal(curDigit+1, favNum, favNumCountSoFar, i, (i==nonFavNum?nonFavNumCountSoFar+1:1), isEqual && (i==(s[curDigit]-'0')));
    } 
    return res;
}
long long res = 0;
for(int favNumber = 0; favNumber < 10; ++favNumber)
    res += f_equal(0, favNumber,0, -1, 0, true);
float getCount(int x, int y) {
    if(x == y) return 0.0; // Special case (no numbers are between x and y)
    return INFINITY;       // The closest value to the correct answer that a computer can use
}