poj--1011sticks

来源:互联网 发布:c语言分割字符串函数 编辑:程序博客网 时间:2024/06/05 10:17

Sticks
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 113750 Accepted: 26131

Description

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

95 2 1 5 2 1 5 2 141 2 3 40

Sample Output

65

思路:深搜,剪枝。能被木棍总和整除的是可能的原始木棍长度。从木棍中最长的长度开始枚举所有可能。

每次搜进去有两种情况,当前根木棍拼完,还是未拼完。


#include<stdio.h>

#include<string.h>
#include<stdlib.h>


int n, stick[65], record[65], flag, sum, len, count;//stick存放所有木棍长度,record标记此木棍是否被用过,

flag标记,若找到最短,则不需继续寻找。sum是所有木棍长度和,len是每次枚举的小棍的长度,count是当前枚举情况下应拼出的小棍个数



int cmp(const void *a, const void *b){
return *(int *)b - *(int *)a;
}//对木棍长度从达到小排序


void dfs(int l, int num, int p){//  l是已经拼好了几根,num是当前这一根拼好的长度,p是小木棍的下标
int i, state = -1;//每次state置为-1
if(l == count){//若拼好的根数到达应该的,说明拼接成功
flag = 1;
return ;
}
for(i = p; i < n && !flag; i++){//!flag是没拼接成功时,每次循环选择木棍时都判断是否已经拼接成功,若成功,则不需继续拼接。不然从p开始,是因为找的是子集而非全排列

if(!record[i] && stick[i] != state){//若没被用过且不是递归回来时上一根已经用过的木棍,这里是剪枝,对应下面的state = stick[i],即当递归回溯时,若是当前回溯回来,

说明当前长度的木棍不能拼接上去,则用state记录这个长度,再试下一根时,避过这个长度的木棍

record[i] = 1;

if(num + stick[i] == len)//只有两种情况,当选了当前木棍正好拼接成一根要拼的木棍时,进入下一层递归,拼接好的木棍个数加1,当前正在拼的木棍长度恢复为0,且下一次

重新从第一根下标为0的木棍开始选

dfs(l + 1, 0, 0);
else if(num + stick[i] < len)//第二种情况,当选了当前木棍到不了要拼的长度时,进入下一层,当前正在拼的木棍长度变为加上刚选的长度,下一次从本次选的木棍的下一根开始选
dfs(l, num + stick[i], i + 1);
record[i] = 0;
state = stick[i];
if(num == 0)//若回溯回来时,发现是第一根(用当前木棍已经拼好的长度是0来表示),说明第一根是不满足的,那么就算再挑选别的木棍来代替,这一根也总会出现在别的木棍里,同理也不会满足,故直接跳出循环,回溯到上一层递归,重选上一根
break;
}
}
}


int main(){
int i;
while(scanf("%d", &n) && n){
sum = 0;
flag = 0;
memset(record, 0, sizeof(record));
for(i = 0; i < n; i++){
scanf("%d", &stick[i]);
sum += stick[i];
}
qsort(stick, n, sizeof(stick[0]), cmp);
for(i = stick[0]; i <= sum; i++){
if(sum % i == 0){
len = i;
count = sum / i;
dfs(0, 0, 0);
if(flag == 1){
printf("%d\n", len);
break;
}
}
}
}
return 0;
}
0 0
原创粉丝点击