POJ 1011剪枝的应用

来源:互联网 发布:苹果拍照软件搞怪 编辑:程序博客网 时间:2024/06/03 19:05

转载请注明来源  谢谢



#include<iostream>

#include<vector>
#include<algorithm>
using namespace std;


const int MAX = 100;
int mark[MAX],stickLength,num;
int sticks[MAX];//这里用数组而不是vector储存棒子的长度


bool dfs(int LastStickCount, int eachLastLen)
{
if (LastStickCount == 0 && eachLastLen == 0)
return true;
if (LastStickCount == 0)
return false;
if (eachLastLen == 0)
eachLastLen = stickLength;


for (int i = 0; i < num; i++)
{
if (sticks[i]>eachLastLen || mark[i] != 0)
continue;
if (i > 0 && mark[i - 1] == 0 && sticks[i] == sticks[i - 1])//剪枝1:在某一位置某一长度尝试失败,那么与它相同长度的棒子在同一位置就没必要尝试了,结果一定失败
continue;


mark[i] = 1;
if (dfs(LastStickCount - 1, eachLastLen - sticks[i]))
return true;


mark[i] = 0;


if (eachLastLen == stickLength || sticks[i] == eachLastLen)//剪枝2:如果尝试的位置是棍的最初位置,那么这个位置尝试失败一定是棍子的长度有问题,因为如果这个                                                                                                                                         位置最长的棒子尝试失败,那这根棒子必将出现在下面的棍子的最初位置,肯定也是尝试失败,
                            return false;                                                                       因此失败的话就直接换棍子的长度。
                                                                                                                             


                                                                                                                        //如果尝试的位置是棍的最后位置,如果这个位置尝试成功,但是下面的棍子组合却出现失败,
                                                                                                                          那肯定也是因为棍的长度有问题,因为如果将最后一根棒子用更短的几根棒子替代的话,
                                                                                                                          这根被替代的棒子肯定会出现在下面那些棍子的组合中,结局肯定也是失败。
                                                                                                                          再细化说,这根被代替的棒子肯定会出现在下面某根棍子中,
                                                                                                                          如果下面这根棍子组装成功的话,那当初用那几根小棒子也肯定能组装成功

}


return false;
}


bool compare(int a, int  b)
{
return a > b;
};


int main()
{
while (cin >> num&&num != 0)
{
int totalLength = 0;
for (int i = 0; i < num; i++)
{
cin >> sticks[i];
mark[i] = 0;
totalLength += sticks[i];
}


sort(sticks, sticks+num, compare);


for (stickLength = sticks[0]; stickLength <= totalLength; stickLength++)
{
if (totalLength%stickLength != 0)//剪枝3:如果不是因数就没必要进行尝试了,因为木棍要等长,那肯定要能整除总长度
continue;
if (dfs(num, stickLength))
{
cout << stickLength << endl;
break;
}
}
}


return 0;
}
0 0