POJ 1101 深搜的剪枝
2018-02-04 19:08
253 查看
题目描述:
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were
originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the
file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
Sample Input
Sample Output
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std ;
const int Max = 4097 ;
int n , weight[Max] , sum ;
int package[Max] , top ;
int book[Max] ;
int DFS( int stick , int res , int i ){
if( res == 0 && stick == n ) // package[i] 时恰好全部用完,返回 1
return 1 ;
if( res == 0 ) // 刚组合了一个 package[i] , 但是还有棍子还用过,重置继续组合
res = package[i] ;
for( int j = n ; j >= 1 ; --j )
if( res >= weight[j] && book[j] == 0 ){
if( j != n && book[j+1] == 0 && weight[j] == weight[j+1] ) // 相同大小的棍子不用重复搜索
continue ;
book[j] = 1 ;
if( DFS( stick+1 , res-weight[j] , i ) )
return 1 ;
else{
book[j] = 0 ; // 回溯,这根棍子无解
if( res == package[i] || weight[j] == res ) // 如果根本选,得不到组合;刚才选的就是剩下的,却也无解
return 0 ;
}
}
return 0 ;
}
int main(){
while( cin >> n && n ){
sum = 0 ;
for( int i = 1 ; i <= n ; ++i ){
cin >> weight[i] ;
sum += weight[i] ;
}
sort( weight+1 , weight+n+1 ) ; // 让小的可以有更多组合
if( weight
> sum >> 1 ){ // 如果最大的棍子比总和的一般还要大,就只有一根了
cout << sum << endl ;
continue ;
}
top = 0 ;
for( int i = weight
; i <= sum ; ++i )
if( sum % i == 0 )
package[++top] = i ; // package 数组保存因子,因为要恰好组合,n 肯定是 i 的倍数
for( int i = 1 ; i <= top ; ++i ){
memset( book , 0 , sizeof( book ) ) ;
if( DFS( 0 , package[i] , i ) ){
cout << package[i] << endl ;
break ;
}
}
}
return 0 ;
}
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were
originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the
file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std ;
const int Max = 4097 ;
int n , weight[Max] , sum ;
int package[Max] , top ;
int book[Max] ;
int DFS( int stick , int res , int i ){
if( res == 0 && stick == n ) // package[i] 时恰好全部用完,返回 1
return 1 ;
if( res == 0 ) // 刚组合了一个 package[i] , 但是还有棍子还用过,重置继续组合
res = package[i] ;
for( int j = n ; j >= 1 ; --j )
if( res >= weight[j] && book[j] == 0 ){
if( j != n && book[j+1] == 0 && weight[j] == weight[j+1] ) // 相同大小的棍子不用重复搜索
continue ;
book[j] = 1 ;
if( DFS( stick+1 , res-weight[j] , i ) )
return 1 ;
else{
book[j] = 0 ; // 回溯,这根棍子无解
if( res == package[i] || weight[j] == res ) // 如果根本选,得不到组合;刚才选的就是剩下的,却也无解
return 0 ;
}
}
return 0 ;
}
int main(){
while( cin >> n && n ){
sum = 0 ;
for( int i = 1 ; i <= n ; ++i ){
cin >> weight[i] ;
sum += weight[i] ;
}
sort( weight+1 , weight+n+1 ) ; // 让小的可以有更多组合
if( weight
> sum >> 1 ){ // 如果最大的棍子比总和的一般还要大,就只有一根了
cout << sum << endl ;
continue ;
}
top = 0 ;
for( int i = weight
; i <= sum ; ++i )
if( sum % i == 0 )
package[++top] = i ; // package 数组保存因子,因为要恰好组合,n 肯定是 i 的倍数
for( int i = 1 ; i <= top ; ++i ){
memset( book , 0 , sizeof( book ) ) ;
if( DFS( 0 , package[i] , i ) ){
cout << package[i] << endl ;
break ;
}
}
}
return 0 ;
}
相关文章推荐
- 搜索 + 剪枝 --- POJ 1101 : Sticks
- 搜索 + 剪枝 --- POJ 1101 : Sticks
- POJ 1101 简单BFS+题意
- poj 1101 The Game
- POJ 1101 Sticks
- 不要丧呀&&POJ 2362 && [剪枝]&&[dfs]
- POJ-3278 Catch That Cow(广搜+剪枝)
- POJ 3900 The Robbery (dfs暴搜+剪枝)
- poj 1190 生日蛋糕 , 强剪枝
- POJ1190 生日蛋糕(DFS剪枝)
- POJ 生日蛋糕(DFS 巧妙剪枝)
- POJ-1011-经典搜索题(深搜+剪枝)
- POJ 1579 解法二用动态规划给递归剪枝,减少重复计算。此题一开始没想到用此法耗费了不少时间。
- POJ 3134 Power Calculus ID-DFS +剪枝
- POJ 1011 Sticks 深搜+剪枝
- poj 1980 Unit Fraction Partition 深搜剪枝
- (POJ 1054)The Troublesome Frog <暴力枚举+剪枝 || DP>
- POJ 1751 Highways(最小生成树+剪枝)
- POJ-3985:Knight's Problem(特殊的bfs剪枝以及hash)
- poj1101 The Game