此题耗费了我一下午的时间 主要算法漏洞 :即使是判断一个木棒能够组成指定的长度时,但是占据了其他木棒所需要得木棒,如下面这组数据
9
15 3 2 11 8 8 8 13 4
错误代码
//
// main.cpp
// uva 307 - Sticks
//
// Created by XD on 15/8/3.
// Copyright (c) 2015年 XD. All rights reserved.
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespace std ;
int n ;
int sticks[100] ;
int l ;
int num ;
int cmp( const int &a, const int &b ){
if( a > b )
return 1;
else
return 0;
}
int max(int i , int j )
{
return i > j ? i : j ;
}
int visit[100] ;
bool canBeL(int s,int nl )
{
if(nl == 0 )
{
return true ;
}
else if(s == n-1 )
{
return false ;
}
int pre = -1 ;
for (int i = s + 1; i < n; i++) {
if (pre!=sticks[i] && !visit[i] && sticks[i] <= nl) {
visit[i] = 1 ;
pre =sticks[i] ;
nl -= sticks[i] ;
if (canBeL(i , nl)) {
return true ;
}
else{
visit[i] = 0 ;
nl += sticks[i] ;
}
}
}
return false ;
}
bool dfs(int s)
{
if (s == n ) {
return true ;
}
if (visit[s] == 1) {
return dfs(s + 1) ;
}
visit[s] = 1 ;
//这样写就出现了上面所说的错误
if (canBeL(s,l - sticks[s] )) {
return dfs(s + 1) ;
}
return false ;
}
int main() {
int m ;
int sum =0 ;
while (scanf("%d" ,&n)==1 && n!= 0) {
m = 0 ;
sum = 0 ;
memset(sticks, 0, sizeof(sticks)) ;
for (int i =0 ;i < n ;i++) {
scanf("%d" , &sticks[i]) ;
m = max(m , sticks[i]) ;
sum += sticks[i] ;
}
sort(sticks, sticks + n ,cmp) ;
for(l = m ; l <= sum ; l++ )
{
if (sum % l == 0 ) {
memset(visit, 0, sizeof(visit)) ;
if (dfs(0)){
printf("%d\n" , l) ;
break ;
}
}
}
}
return 0;
}
正确代码
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespace std ;
struct stick{
int length; //长度
int mark; //标记是否被使用过
};
stick sticks[64];
int n,num,sum;
int cmp(const stick &s1,const stick &s2){
return s1.length>s2.length;
}
//len当前的长度,count当前长度为len的木棒的根数
int dfs(int len,int l,int count,int pos){
if(len==sum)return 1;//如果当期的长度就是所有木棒的总长
if(count==num)return 1;
for(int i=pos;i<n;i++){
if(sticks[i].mark)continue;
//没有被标记过的
if(len==(sticks[i].length+l)){
sticks[i].mark=1;
if(dfs(len,0,count+1,0))//长度相等时,还是要从第一根开始搜
return 1;
sticks[i].mark=0;
return 0;
}else if(len>(sticks[i].length+l)){
sticks[i].mark=1;
l+=sticks[i].length;
if(dfs(len,l,count,i+1))
return 1;
l-=sticks[i].length;//如果不成功,就要恢复
sticks[i].mark=0;
if(l==0)return 0;//当前搜索,如果前面的l为0,但第一根没有用上,那么这根木棒就要舍弃
while(sticks[i].length==sticks[i+1].length)i++;//这根不成功的话,则相连的长度相同的不要
}
}
return 0;
}
int main(){
while(scanf("%d",&n)!=EOF){
if(n==0)break;
sum=0;
for(int i=0;i<n;i++){
scanf("%d",&sticks[i].length);
sticks[i].mark=0;
sum+=sticks[i].length;
}
sort(sticks,sticks+n,cmp);
for(int len=sticks[0].length;len<=sum;len++){
if(sum%len)continue;
num=sum/len; //原来长度为len的木棒的根数
if(dfs(len,0,0,0)){
printf("%d\n",len);
break;
}
}
}
return 0;
}