西工大 poj sticks

本文介绍了一道经典的深搜题目——西工大POJ sticks,讲解了解题思路和剪枝技巧。通过由大到小的排序、利用排序剪枝、避免重复搜索等方法,实现原棒最小可能长度的搜索。文章详细阐述了搜索顺序、递归参数的传递、状态判断等方面的策略。
摘要由CSDN通过智能技术生成

什么都不说先上代码



#include <iostream>

int n;              //小棒总数
int len;            //当前枚举的原棒长度
int parts;          //当前组合的原棒数
int max;            //最长小棒的长度
int sum;            //所有小棒的总长
int tail;           //指向尾部长度较小的棒
int l[64][2];       //存储小棒相关信息
bool used[64];      //标记小棒是否使用

void sort() {
//对小棒进行排序
for (int i=0;i<n;i++)
{
for (int j=i+1;j<n;j++)
{
if (l[0]<l[j][0])
{
int t=l[0];
l[0]=l[j][0];
l[j][0]=t;
}
}
}
//给每一个小棒加上指针,指向下一个长度不同的小棒
int i=0;
while (i<n)
{
int j=i+1;
while (j<n&&l[j][0]==l[0]) j++;
for (int k=i;k<j;k++) l[k][1]=j;
i=j;
}
}

void initial() {
//初始化设置所有小棒均未使用
for (int i=0;i<n;i++)
{
used=false;
}
int sumr=0;
//计算一个指针,其后小棒相加之和大约为一根原棒长度
int i=n-1;
for (int i=n-1;i>=0;i--)
{
sumr+=l[0];
if (sumr>len) break;
}
tail=i;
}

inline int sumres(int m) {
//计算下标大于等于m且未使用的小棒总长之和
int sumr=0;
for (int i=m;i<n;i++) {
if (used==false)
sumr+=l[0];
}
return sumr;
}

bool search(int res,int next,int cpl)
//策略2:用next存储当前可用的下一支小棒
{
//修正参数,当res=len时表示正好拼接成一支原棒
if (res==len) {
res=0;
next=1;
cpl++;
}
//当已拼出的原棒为应拼出原棒时,返回TRUE
if (cpl==parts)
return true;
int i=next;
while (i<n) {
//尝试未使用的小棒
if (used==false) {
//判断接入此小棒是否超出原棒长度
if (res+l[0]<=len) {
//将该小棒标为已使用
used=true;
//递归搜索,一旦成功则不断向上一级返回TRUE
if (search(res+l[0],i+1,cpl)) return true;
//还原该小棒为未使用
used=false;
//策略4:第一次拼接当前原棒无解则当前状态必定无解,跳出
if (res==0) break;
//策略5:若尝试一根小棒恰能组合出当前原棒的剩余长度的小棒失败,则不再尝试比它更小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值