您的位置:首页 > 其它

POJ 1011(Sticks)解题纠错

2011-03-27 20:57 351 查看
以下来自http://topic.csdn.net/u/20110324/20/f62e1942-a2bc-4ee4-b015-98e2102cd46c.html?seed=1228193625&r=72409442#r_72409442

#include<iostream>
#include<cstdlib>
#include<map>
using namespace std;

int everyLength[64];//输入的每一节小木棍的长度
bool isUsed[64];//跟踪每个小木棍是否被使用
map<int,int> numPost;//记录相同长度小木棍的最后一个位置
int groupNum,groupLength;//记录有多少根棍,每个棍多长

//compare函数,用于qsort函数中使用。
int compare(const void *n1,const void *n2){
return(*((int*)n2)-*((int*)n1));
}
//参数为原始木棒长度,小木棒总个数,上一次取木棒的位置
bool dealwith(int minlength,int number,int lastnote){
//开始循环找木棒拼会原始木棒,当然从最大的那根开始
for(int i=lastnote+1;i<number;++i){
//首先看是否被使用过
if(isUsed[i]){
//如果当前小木棍大于所需要的长度,那么跳过所有该长度的小木棍
if(minlength-everyLength[i]<0){
i=numPost[everyLength[i]];
continue;
}
//如果成功拼出一个木棍
else if(minlength-everyLength[i]==0){
isUsed[i]=false;//标记该木棍被使用了。
--groupNum;     //需要拼接的小木棍少一个
//如果只剩下一个木棍,则一定成功了。
if(groupNum==1)
return true;
if(dealwith(groupLength,number,0))//如果后面的木棍返回成功,说明全部成功了
return true;
else{                             //如果后面的木棍拼接不成功,那么说明这个木棍是有问题的
++groupNum;                   //将为拼接的原始木棍数+1
isUsed[i]=true;               //使用的小木棍设置为未使用
i=numPost[everyLength[i]];    //并且这个小木棍一样长度的木棍都不适用
continue;
}
}
else{                                  //如果还是不够长度,那么继续
isUsed[i]=false;                   //设置该木棍被使用
if(dealwith(minlength-everyLength[i],number,i))     //如果返回成功,则成功拼接
return true;
else{
isUsed[i]=true;                                //如果不成功,那么该木棍不可以使用
if(minlength==groupLength)                      //并且,如果这是一个原始木棍第一个最长小木棍拼接处返回的,
return false;                               //则说明这个长木棍没办法和下面的小木棍结合,故直接返回上一根拼接好的木棍
i=numPost[everyLength[i]];
}
}

}
}
return false;
}
int main(){
int sticksNum;
while(cin>>sticksNum){
if(sticksNum==0)
break;
int i,sum(0);
for(i=0;i<sticksNum;++i){
cin>>everyLength[i];
isUsed[i]=true;
sum+=everyLength[i];
}
qsort(everyLength,i,sizeof(int),compare);//按照从大到小排列数据
for(int j=0;j<i;++j)
numPost[everyLength[j]]=j;//收集每个相同长度小木棒的最后一个的位置

//找到能被木棒之和整除的数据。
for(int j=everyLength[0]+1;;++j){
if(sum%j==0){
groupLength=j;//记录下当前最小原始木棒长度
groupNum=sum/j;//记录下此长度下有多少个木棒
if(dealwith(j,i,-1)){//若这些小木棒可以拼成原始木棒,则打印。
cout<<j<<endl;
break;
}
}
}
}
return 0;
}


POJ报的错误是超时,原因可能是有些用例陷入死循环,如:

2
1 1
5
3 7 11 13 17
3
2 4 8

经检查,有以下问题:

(1)isUsed只做了一次初始化;

(2)匹配成功一根木棒后没有从头开始搜索;

(3)如果后面不成功,还在继续搜索。

以下修改AC:

#include<iostream>
#include<cstdlib>
#include<map>
using namespace std;

int everyLength[64];//输入的每一节小木棍的长度
bool isUsed[64];//跟踪每个小木棍是否被使用
map<int,int> numPost;//记录相同长度小木棍的最后一个位置
int groupNum,groupLength;//记录有多少根棍,每个棍多长

//compare函数,用于qsort函数中使用。
int compare(const void *n1,const void *n2){
return(*((int*)n2)-*((int*)n1));
}
//参数为原始木棒长度,小木棒总个数,上一次取木棒的位置
bool dealwith(int minlength,int number,int lastnote){
//开始循环找木棒拼会原始木棒,当然从最大的那根开始
for(int i=lastnote+1;i<number;++i){
//首先看是否被使用过
if(isUsed[i]){
//如果当前小木棍大于所需要的长度,那么跳过所有该长度的小木棍
if(minlength-everyLength[i]<0){
i=numPost[everyLength[i]];
continue;
}
//如果成功拼出一个木棍
else if(minlength-everyLength[i]==0){
isUsed[i]=false;//标记该木棍被使用了。
--groupNum;     //需要拼接的小木棍少一个
//如果只剩下一个木棍,则一定成功了。
if(groupNum<=1)//if(groupNum==1)
return true;
//if(dealwith(groupLength,number,0))//如果后面的木棍返回成功,说明全部成功了
if(dealwith(groupLength,number,-1))//如果后面的木棍返回成功,说明全部成功了
return true;
else{                             //如果后面的木棍拼接不成功,那么说明这个木棍是有问题的
++groupNum;                   //将为拼接的原始木棍数+1
isUsed[i]=true;               //使用的小木棍设置为未使用
//i=numPost[everyLength[i]];    //并且这个小木棍一样长度的木棍都不适用
return false;//continue;
}
}
else{                                  //如果还是不够长度,那么继续
isUsed[i]=false;                   //设置该木棍被使用
if(dealwith(minlength-everyLength[i],number,i))     //如果返回成功,则成功拼接
return true;
else{
isUsed[i]=true;                                //如果不成功,那么该木棍不可以使用
if(minlength==groupLength)                      //并且,如果这是一个原始木棍第一个最长小木棍拼接处返回的,
return false;                               //则说明这个长木棍没办法和下面的小木棍结合,故直接返回上一根拼接好的木棍
i=numPost[everyLength[i]];
}
}

}
}
return false;
}
int main(){
int sticksNum;
while(cin>>sticksNum){
if(sticksNum==0)
break;
int i,sum(0);
for(i=0;i<sticksNum;++i){
cin>>everyLength[i];
isUsed[i]=true;
sum+=everyLength[i];
}
qsort(everyLength,i,sizeof(int),compare);//按照从大到小排列数据
for(int j=0;j<i;++j)
numPost[everyLength[j]]=j;//收集每个相同长度小木棒的最后一个的位置

//找到能被木棒之和整除的数据。
for(int j=everyLength[0];j<=sum;++j){//for(int j=everyLength[0]+1;;++j){
if(sum%j==0){
groupLength=j;//记录下当前最小原始木棒长度
groupNum=sum/j;//记录下此长度下有多少个木棒
for(int k=0;k<sticksNum;++k)isUsed[k]=true;

if(dealwith(j,i,-1)){//若这些小木棒可以拼成原始木棒,则打印。
cout<<j<<endl;
break;
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: