今天看到July博客扩展KSum问题扩展到中兴的子集和面试题,发现还有一大类回溯法及分支限界还没回顾,
回溯法有一个搜索的框架,对于子集和问题类似于选或不选,因此联想到之前碰到的组合数问题,C(n, k) 因为光打印出解都有指数级的行数,显然不是一般的算法,而是回溯法这类处理较复杂的题目。而且博客还说这个有点类似于01背包问题。
Subsets(int sum ,int n, int*a)
{
<span style="white-space:pre"> </span>if(sum==n)//最后一个match
<span style="white-space:pre"> </span>print 选的元素集 return;
<span style="white-space:pre"> </span>不选n,
<span style="white-space:pre"> </span>Subsets(sum,n-1,a);
<span style="white-space:pre"> </span>选n,
<span style="white-space:pre"> </span>Subsets(sum-n,n-1,a);
}
但是没明白为啥要list实现,而且还要reverse。。。终于明白,只是写成一个加法式子,没有太多算法层面的含义,并且数组要从大加到小~~~
http://tech-wonderland.net/blog/summary-of-ksum-problems.html
http://blog.csdn.net/v_july_v/article/details/6419466
http://www.cnblogs.com/microgrape/archive/2011/05/11/2043814.html
从这里可以理解,其实树的根先序其实就是深度优先,递归版本也是逐个递归他的下一层分钟,或者叫回溯法,从左边开始找到底,找不到了,再回溯一层往右看一个,逐个进行
今天重新写了一下C(n,k)的代码,发现还是不方便用邹波的from to来写,需要两个递归参数,至少,其他的都可以变成全局。selectk 表示当前的选择k个数选了几个,如果selectk=k 表示递归的结果是需要的,selectn表示选择了多少个数,如果=n表示已经遍历完这个n个数了,初始调用是dfs(0,k,0,n)
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
//int k=2,n=6;
#define MAXNUM 100000
//int num[MAXNUM];
bool selected[MAXNUM];
int cnt=0,T,n,m,k;
int kth;
void dfs(int selectk,int k,int selectn,int n,string num)//dfs(1) as start
{
if(k>n) return;
if(selectn==n)
{
if(selectk==k)
{
/*
for(int j=0;j<n;j++)
{
if(select[j]==true)
cout<<num[j];
}*/
cnt++;
if(cnt==kth)
{
for(int j=0;j<n;j++)
{
if(selected[j]==true)
cout<<"1";
else
cout<<"0";
}
cout<<endl;
}
}
}
else
{
selected[selectn]=false;
dfs(selectk+1,k,selectn+1,n,num);
selected[selectn]=true;
dfs(selectk,k,selectn+1,n,num);
}
}
int main()
{
//int num[MAXNUM]={1,3,4,5,8,9};
//bool selected[MAXNUM]={false,false,false,false,false,false};
/*
for(int i=0;i<n;i++)
{
cin>>num[i];
}*/
scanf("%d",&T);
while(T--)
{
cnt=0;
scanf("%d%d%d",&n,&m,&kth);
string str="";
for(int i=0;i<n;i++)
str+="0";
for(int i=0;i<m;i++)
str+="1";
memset(selected,0,sizeof(bool)*(n+m));
dfs(0,n,0,n+m,str);
if(cnt<kth)
cout<<"Impossible"<<endl;
}
return 0;
}
拿了微软秋令营的一道题目练手,其实更快的方法是用next_permutaion来实现。