以前想做DFS,不知道回溯怎么用代码实现,现在发现很简单,用回溯的递归就能搞定。 PKU ACM 3140,4107,1655,3099都是类似的例子。
好多问题都可能归结成当前子树的规模,DFS,就是对某一个节点的所有没有访问的子节点一个个访问,最后归结起来就能返回。
帖一些回溯的代码:下面的代码解决了三个问题:1:n皇后,2找出一个集合中所有满足某个条件的子集,3显示一个集合的所有子集。 注意变量数组的空间只需要一个就够了,因为是递归调用。
#include <iostream>
#include <cmath>
using namespace std;
int Num;
bool Place (int k, int i, int *x)
{
for(int j=0;j<k;j++)
if( (x[j]==i) || ( abs( x[j]-i)==abs(j-k) ) ) return false;
return true;
}
void NQueens(int k, int n, int *x)
{
for(int i=0; i<n;i++)
{
if( Place(k,i,x)) //»ØËÝ·¨£¬ÀûÓóÌÐò¾Íд³öËùÓпÉÄÜÐÔ£¬ÓÉÓÚÊǵ¥Ị̈߳¬ËùÒÔ»áÖ´ÐÐÍêÒ»¸öÔÙÖ´ÐÐÏÂÒ»¸ö£¬ËùÒÔ²»ÓÃ×Ô¼ºÐ´³ö»ØËÝ£¬ÎÒÒÔǰµ±³ÉÊ÷дÁË£¬¸´ÔÓµÄÌ«¶à
{ //²»Ðеϰ£¬¾Í·ÅÆúÁËÒ»Ñù
x[k] = i;
if( k== n-1){
for(int m=0;m<n;m++)
cout << x[m]<<" ";
cout<<endl;
Num++;
}
else NQueens(k+1,n,x);
}
}
}
void NQueens(int n, int *x)
{
Num = 0;
NQueens(0,n,x);
cout<<Num<<endl;
}
int Get(int s, int wi,int D)
{
if( s + wi > D)
return 1;
else if( s + wi == D )
return 0;
return -1;
}
void Sum(int k, int n, int *x,int *out, int kk,int D, int s)
{ // ´ÓÔÊý×éµÚk¸ö¿ªÊ¼¼ÌÐøËÑË÷£¬ ÔÊý×én£¬*x
// *out kk ½á¹ûºÍ½á¹û½«Òª±£´æµÄϱê
// Ä¿±ê ºÍ ÏÖÔÚ״̬
for(int i=k; i<n;i++) // »ØËÝ·¨Ð§ÂÊÈçºÎ£¿
{
int tmp = Get( s, x[i],D);
if( tmp == 0 ) //ÏÔʾ³öÀ´
{
out[kk] = x[i];
for(int j=0;j<=kk;j++)
cout<<out[j]<<" ";
cout<<endl;
}
else if( tmp ==-1)
{
out[kk] = x[i];
if( i<n-1)
Sum(i+1,n,x,out,kk+1,D,s+x[i]); //Éî¶ÈÓÅÏÈ
}
else if( tmp ==1) //²»´¦Àí£¬Ï൱ÓÚ¼ôÈ¥ÁËÊ÷µÄÒ»¸öÖ§
{
}
}
}
void OnPaint(int k, char * out)
{
for(int i=0;i<=k;i++)
cout<<out[i]<<" ";
cout<<endl;
}
void Show(int p, int n, char *d, char *out,int k)
{
for(int i=p;i<n;i++)
{
out[k] = d[i]; OnPaint(k,out);
Show( i+1,n,d,out,k+1);
}
}
void ShowAllChildSet(int n, char * d)
{
char *out = new char[n];
Show(0,n,d,out,0);
delete [] out;
}
int main()
{
/* int n=10;
int *x =new int[n];
NQueens( n,x);
*/
/* int n =5;
int W[10] = {7,24,11,13,7};
int *out = new int[n];
Sum(0, n, W,out,0,31,0);
*/
const int n=4;
char c[n] = {'a','b','c','d'};
char *d = &c[0];//{'a','b'};
ShowAllChildSet(n,d);
return 0;
}