C 将时间分为两个方框,并找出最小差异
开始学习递归,我被这个简单的问题困住了。我相信有更多的优化方法可以做到这一点,但首先我尝试学习bruteforce方法 我有A包和B包,有C 将时间分为两个方框,并找出最小差异,c,algorithm,recursion,C,Algorithm,Recursion,开始学习递归,我被这个简单的问题困住了。我相信有更多的优化方法可以做到这一点,但首先我尝试学习bruteforce方法 我有A包和B包,有n个项目每个项目都有一定的时间(小数点后两位的浮动)。这样做的目的是通过两个袋子分配物品,并获得两个袋子之间的最小差异。想法是尝试所有可能的结果 我认为只有一个包(比如说A包)中有,因为另一个包将包含A包中没有的所有项目,因此差值将是总时间总和的绝对值-2*A包中项目时间的总和 我这样调用递归函数: min = total_time; recursive(0,
n个项目
每个项目都有一定的时间(小数点后两位的浮动)。这样做的目的是通过两个袋子分配物品,并获得两个袋子之间的最小差异。想法是尝试所有可能的结果
我认为只有一个包(比如说A包)中有,因为另一个包将包含A包中没有的所有项目,因此差值将是总时间总和的绝对值-2*A包中项目时间的总和
我这样调用递归函数:
min = total_time;
recursive(0, items_number - 1, 0);
该函数的代码如下所示:
void recursive(int index, int step, float sum) {
sum += items_time[index];
float difference = fabs(total_time - 2 * sum);
if (min > difference) {
min = difference;
}
if (!(min == 0.00 || step == 1 || sum > middle_time)) {
int i;
for (i = 0; i < items_number; i++) {
if (i != index) {
recursive(i, step - 1, sum);
}
}
}
}
void recursive(整数索引、整数步长、浮点和){
总和+=项目时间[索引];
浮动差=fabs(总时间-2*和);
如果(最小值>差值){
最小值=差值;
}
如果(!(最小==0.00 | |步==1 | |和>中间时间)){
int i;
对于(i=0;i
假设我有4个项目的时间1.23、2.17、2.95、2.31
我得到的结果是0.30
。我相信这是正确的结果,但我几乎可以肯定,如果这是纯粹的改变,因为如果我尝试更大的情况,程序会在一段时间后停止。可能是因为递归树变得更大了
有人能给我指个方向吗?你的问题叫做“问题”。这是NP难的,在某一点之后,它将需要一段很长的时间才能完成:随着要测试的案例数量的增长,树将以指数形式增大
分区问题是众所周知的,并且在internet上有很好的文档记录。存在一些优化的解决方案您的方法不是简单的暴力方法,它只是遍历项目列表并递归地将其放入包A和包B中,选择差异最小的情况,例如:
double recurse(double arr[], int n, double l, double r)
{
double ll, rr;
if (n == 0) return fabs(l - r);
ll = recurse(arr + 1, n - 1, l + *arr, r);
rr = recurse(arr + 1, n - 1, l, r + *arr);
if (ll > rr) return rr;
return ll;
}
(这段代码非常幼稚——它并不是很早就出现明显的非最佳情况,而且在交换行李A和行李B的情况下,每种情况下计算两次也会浪费时间。然而,这是一种蛮力。)
最大递归深度是项数n
,调用递归函数2^n-1
次
在您的代码中,您可以将同一物品反复放入袋子中:
for (i = 0; i < number_of_pizzas; i++) {
if (i != index) {
recursive(i, step - 1, sum);
}
}
for(i=0;i
此循环阻止您处理当前项目,但将愉快地处理在早期递归中第二次(或第三次)放入包中的项目。如果你想使用这种方法,你必须保持哪个物品在哪个袋子里的状态
另外,我不明白你的
步骤。从步骤-1开始,当步骤==1
时停止递归。这意味着您正在考虑n-2
项。我知道其他物品在另一个袋子里,但这是一个奇怪的情况,它不会让你找到解决方案,比如说,{8.0,2.4,2.4,2.8}
好的,在澄清之后,让我(希望)为你指出一个方向:
让我们假设您知道n
是什么,在n项中提到。在您的示例中,它是2n
是4
,使n=2
。让我们选择另一个n
,这次是3
,我们的时间应该是:
1.00
2.00
3.00
4.00
5.00
6.00
现在,我们已经知道答案是什么了;您所说的都是正确的,最佳情况下,每个行李的n=3
时间
s总计为中间时间
,在这种情况下为21/2=10.5
。由于整数可能永远不会和带有小数点的数字相加,10.5:10.5
在本例中可能永远无法实现,但是10:11
可以,并且您可以通过6.00+3.00+1.00
(3个元素)获得10
,因此。。。是的,答案就是1
你会让电脑怎么计算呢?好;回想一下我一开始说的话:
让我们假设您知道什么是n
在这种情况下,一个天真的程序员可能会简单地将所有这些放在2或3个嵌套的for
循环中2
如果他/她知道另一半将在您选择一半时确定(只需固定我们组中的第一个元素,因为该元素将包含在其中一个组中),您也知道<代码>3
如果他/她不知道的话。让我们用2
:
...
float difference;
int i;
for ( i = 1; i < items_number; i++ ) {
sum = items_time[0] + items_time[i];
int j;
for ( j = i + 1; j < items_number; j++ ) {
sum += items_time[j];
difference = fabs( total_time - 2 * sum );
if ( min > difference ) {
min = difference;
}
}
}
...
。。。
浮差;
int i;
对于(i=1;i差值){
最小值=差值;
}
}
}
...
让我对代码稍加评论,以便更快地理解:在第一个循环中,它会将第0次、第1次和第2次相加,如您所见;然后它将执行与您相同的检查(计算差异
,并将其与min
进行比较)。让我们称之为012
组。要检查的下一组将是013
,然后是014
,然后是015
;然后023
,依此类推。。。将检查将6分为两个3的每个可能组合
这个操作对计算机来说应该不会有什么累人的问题。即使使用这种简单的方法,最大的尝试次数也将是3次与6次唯一el组合的次数