分支界定是一种在问题的解空间树上搜索问题的解的方法,其实就是剪枝广搜,它始终维护一个上下界用来剪枝,一个限界函数计算对解的最有期望。主要用于解决离散问题的优化。
分支界定的关键问题:
(1)如何确定合适的限界函数
(2)如何组织待处理节点表
(3)如何记录最优解路径
限界函数应该是经过该节点所有搜索路径的最佳期望
最大问题:本质还是广搜,复杂度肯定不低,2^n的节点空间也受不了,试着解决01背包超时又超存,肯定不如DP,也可以解决TSP,排线问题等,
下边自己写的一个01背包,问题一堆,哎,菜鸟一个….
http://acm.hdu.edu.cn/showproblem.php?pid=2602
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 1005
struct ITEM
{
int w,v;
}b[MAXN];
struct NODE
{
int w,v,ve,pos;
bool operator < (const NODE & other)const
{
return ve < other.ve;
}
};
int search(ITEM * b,int num,int vol);
int cmp(const void * a,const void * b);
int expect(NODE a,ITEM * b,int num);
int main()
{
//freopen("Sample Input.txt","r",stdin);
int caseNum;
scanf("%d",&caseNum);
while(caseNum--)
{
int vol,num;
scanf("%d%d",&num,&vol);
for(int i = 0;i < num;i++)
{
scanf("%d",&b[i].v);
}
for(int i = 0;i < num;i++)
{
scanf("%d",&b[i].w);
}
printf("%d\n",search(b,num,vol));
}
}
int search(ITEM * b,int num,int vol)
{
qsort(b,num,sizeof(b[0]),cmp);
/*for(int i = 0;i < num;i++)
{
printf("%d %d\n",b[i].w,b[i].v);
}*/
int min = 0; //贪心的一个最小界
int t = vol;
for(int i = 0;i < num;i++)
{
if(t >= b[i].w)
{
min += b[i].v;
t -= b[i].w;
}
}
/*printf("%d %d\n",vol,min);*/
priority_queue<NODE> que;
NODE fir;
fir.v = 0;
fir.w = vol;
fir.pos = 0;
fir.ve = expect(fir,b,num);
que.push(fir);
while(!que.empty())
{
NODE cur = que.top();
que.pop();
if(cur.pos == num)
{
return cur.v;
}
for(int i = 0;i <= 1;i++)
{
NODE next = cur;
if(i == 1 && next.w < b[cur.pos].w)
{
continue;
}
next.w -= (i * b[cur.pos].w);
next.v += (i * b[cur.pos].v);
next.pos++;
next.ve = expect(next,b,num);
if(next.pos == num && next.v > min)
{
min = next.v;
}
if(next.ve >= min)
{
que.push(next);
}
}
}
}
int cmp(const void * a,const void * b)
{
double rate_a = double(((ITEM *) a) -> v) / ((ITEM *) a) -> w;
double rate_b = double(((ITEM *) b) -> v) / ((ITEM *) b) -> w;
return rate_b - rate_a;
}
int expect(NODE a,ITEM * b,int num) //限界函数
{
if(a.pos == num)
{
return a.v;
}
else
{
return a.v + a.w * b[a.pos].v / b[a.pos].w;
}
}