POJ 1011/DFS:子集划分
问题描述:原有若干sticks,每支stick被分割成若干支,现在要恢复一下。找出这样的子集,使得每个子集的和(plen)相等,并且最小
算法:排序,遍历所有可能plen
剪枝:排序后, a[0] a[1] a[2].....a[n-1],如果想从a[i]开始(不包括i)匹配一个数v,如果i+1,i+2......n-1都匹配不成功了,则肯定i+2,i+3....n-1也匹配不成功了,所以从TLE版本做修改后得到AC版本
TLE:
#include <iostream> #include <algorithm> using namespace std; #define MAX 64 int sticks[MAX]; bool used[MAX]; int stickNum,plen,n; bool compare(int a, int b) { return a > b; } //从beginIndex号开始匹配,下一步要匹配matchLen的stick,在此之前已经匹配了hasMatch条stick bool dfs(int beginIndex,int matchLen,int hasMatch){ //printf("%4d%4d%4d\n",beginIndex,matchLen,hasMatch); if(matchLen==0){ hasMatch++; //printf("hasMatch=%d,stickNum=%d\n",hasMatch,stickNum); if(hasMatch==stickNum){ //printf("hasMatch==stickNum\n"); return true; } for(beginIndex=0;used[beginIndex];beginIndex++); //used[beginIndex]=true; //printf("match=%d begin = %d\n",hasMatch,beginIndex); if(dfs(beginIndex,plen,hasMatch))return true; //used[beginIndex]=false; return false; }else{ if(beginIndex>n-1)return false; for(int i=beginIndex;i<n;i++){ if(used[i])continue; if(sticks[i]>matchLen)continue; if(i>0&&sticks[i]==sticks[i-1]&&!used[i-1])continue; used[i]=true; if(dfs(i+1,matchLen-sticks[i],hasMatch)) return true; used[i]=false; } } //printf("end %4d%4d%4d false\n",beginIndex,matchLen,hasMatch); return false; } int main(int argc, char* argv[]) { int sum = 0; int i; while(scanf("%d",&n)&&n){ sum=0; for( i=0;i<n;i++){ scanf("%d",&sticks[i]); sum += sticks[i]; } bool ok = false; sort(sticks,sticks+n,compare); for(plen=sticks[0];plen<=sum/2;plen++){ if(sum%plen==0){ //used[0]=true; stickNum = sum/plen; if(dfs(0,plen,0)){ ok = true; break; } //used[0]=false; } } if(ok){ printf("%d\n",plen); }else{ printf("%d\n",sum); } memset(used,false,sizeof(used)); } return 0; }
AC:
#include <iostream> #include <algorithm> using namespace std; #define MAX 64 int sticks[MAX]; bool used[MAX]; int stickNum,plen,n; bool compare(int a, int b) { return a > b; } //从beginIndex号开始匹配,下一步要匹配matchLen的stick,在此之前已经匹配了hasMatch条stick bool dfs(int beginIndex,int matchLen,int hasMatch){ //printf("%4d%4d%4d\n",beginIndex,matchLen,hasMatch); if(matchLen==0){ hasMatch++; //printf("hasMatch=%d,stickNum=%d\n",hasMatch,stickNum); if(hasMatch==stickNum){ //printf("hasMatch==stickNum\n"); return true; } for(beginIndex=0;used[beginIndex];beginIndex++); //printf("match=%d begin = %d\n",hasMatch,beginIndex); used[beginIndex]=true; if(dfs(beginIndex+1,plen-sticks[beginIndex],hasMatch))return true; used[beginIndex]=false; return false; }else{ if(beginIndex>n-1)return false; for(int i=beginIndex;i<n;i++){ if(used[i])continue; if(sticks[i]>matchLen)continue; if(i>0&&sticks[i]==sticks[i-1]&&!used[i-1])continue; used[i]=true; if(dfs(i+1,matchLen-sticks[i],hasMatch)) return true; used[i]=false; } } //printf("end %4d%4d%4d false\n",beginIndex,matchLen,hasMatch); return false; } int main(int argc, char* argv[]) { //freopen("i://in.txt","r",stdin); int sum = 0; int i; while(scanf("%d",&n)&&n){ sum=0; for( i=0;i<n;i++){ scanf("%d",&sticks[i]); sum += sticks[i]; } bool ok = false; sort(sticks,sticks+n,compare); for(plen=sticks[0];plen<=sum/2;plen++){ if(sum%plen==0){ used[0]=true; stickNum = sum/plen; if(dfs(0,plen-sticks[0],0)){ ok = true; break; } used[0]=false; } } if(ok){ printf("%d\n",plen); }else{ printf("%d\n",sum); } memset(used,false,sizeof(used)); } return 0; }
躲猫猫社团团长 http://t.sina.com.cn/coolria