剪枝的几条原则:
1.当前的情况不可能到达目标,返回。
2.当前这种情况可能到达目标,但显然不是最优解,返回。
3.记录已取得的当前最优解,用来控制搜索层数。
代码如下:
<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
using namespace std;
int N=0,M=0;//undirected graph N vertex M edges
int StaNum=0;//number of station
int MinSta=0;// min number of station
bool Graph[35+5][35+5]={false};//begin with 1
int StaTo[35+5]={0};//the status of the towns,begin with 1,ths stato[i]++ it's value can be cover and repeat
int act=0;//act is activity number of the towns
int PointDegree[35+5]={0};//save the point's degree
int check()
{
for(int i=1;i<=N;i++)
if(!StaTo[i])
return 0;
return 1;
}
int DFS(int cur)
{
//2 prune
if(StaNum>MinSta)
{
return(0);
}
if(cur>N)
{
//if(act==N)
if(check())
{
if(StaNum<MinSta)
{
MinSta=StaNum;
}
}
}
else
{
//3 prune
int i=0,j=0;
for(i=1;i<=cur-1;i++)
{
if(StaTo[i]==0)
{
for(j=cur;j<=N;j++)
{
if(Graph[i][j])
{
break;
}
}
if(j>N)
{
return(0);//the point i would be unactivity forever
}
}
}
int oldact=act;
//place the source
if(StaTo[cur]==0)
act++;
StaTo[cur]++;
StaNum++;
//activate the neighbour
for(i=1;i<=N;i++)
{
if(Graph[cur][i])
{
if(StaTo[i]==0)
{
act++;
}
StaTo[i]++;
}
}
if(act>oldact)//1 prune
DFS(cur+1);
for(i=1;i<=N;i++)
{
if(Graph[cur][i])
{
StaTo[i]--;
if(StaTo[i]==0)
{
act--;
}
}
}
StaNum--;
StaTo[cur]--;
if(StaTo[cur]==0)
{
act--;
}
//don't place the source
DFS(cur+1);
}
return(0);
}
int test()
{
return(0);
}
int MainProc()
{
while(scanf("%d%d",&N,&M)!=EOF&&(N+M)>0)
{
//init
memset(Graph,false,sizeof(Graph));
memset(StaTo,0,sizeof(StaTo));
memset(PointDegree,0,sizeof(PointDegree));
MinSta=100;
StaNum=0;
act=0;
int toStart=0,toEnd=0;
int i=0;
int MaxDegree=0;
int MaxIndex=0;
for(i=1;i<=M;i++)
{
scanf("%d%d",&toStart,&toEnd);
Graph[toStart][toEnd]=true;
Graph[toEnd][toStart]=true;
}
DFS(1);
printf("%d\n",MinSta );
}
return(0);
}
int main(int argc, char const *argv[])
{
MainProc();
return 0;
}
</span>