您的位置:首页 > 其它

POJ 1011/DFS:子集划分

2011-06-06 18:48 253 查看
问题描述:原有若干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 64int sticks[MAX];bool used[MAX];int stickNum,plen,n;bool compare(int a, int b){return a > b;}//从beginIndex号开始匹配,下一步要匹配matchLen的stick,在此之前已经匹配了hasMatch条stickbool 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;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: