问题描述
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.
输入格式
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.
输出格式
The output should contains the smallest possible length of original sticks, one per line.
解题思路
点击链接,这位大神讲的十分详细了!!!
我的理解
总体思路:
1.题目通过所有值求和为sum,整数i从最大值max到sum,若sum%i=0,则i为可能解。
2.通过递归验证所给木棒是否能组成长度为i的多条木棒。
递归验证思路:
递归有三个参数:1. nowLen:表示当前木棒的长度,2.nowGet表示现在已经拼接的木棒数,3.cnt表示下一个寻找树枝的下标。
递归思路:
如果cnt>n,则返回0。因为下标超了。
如果nowGet=g,则返回1。表示所有的木棒都用完了,成功。
i从cnt到n一次寻找stick[i]是否符合下面两种情况的一种。
1.nowLen+sticks[i].length ==len,表示已经拼成一根完整的木棒,则更新当前木棒数,进行新一根木棒的拼接。
2.nowLen+sticks[i].length<len,表示当前木棒可能能够拼成一根完整的木棒,则更新木棒长度,继续进行木棒拼接。
剪枝条件
1.如果有一根木棒加上去,找不到其他木棒可以和其拼成一整根木棒,则该策略是完全无效的,直接返回0。
2.如果当前木棒不满足要求,则和它等长的木棒一定不满足要求,直接跳过。
代码部分
#include <stdio.h>
#include <algorithm>
using namespace std;
#define USED 1
#define UNUSED 0
#define MAXSIZE 64
struct Stick
{
int length;
int mark;
}sticks[MAXSIZE];
bool cmp(Stick a,Stick b){
return a.length>b.length;
}
int n;
int g;
int len;
int DFS(int nowLen,int nowGet,int cnt)
{
if(cnt>=n) return 0;
if(nowGet == g) return 1;
int i;
for(i=cnt;i<n;i++)
{
if(sticks[i].mark==UNUSED)
{
if(nowLen+sticks[i].length==len)
{
sticks[i].mark = USED;
if(DFS(0,nowGet+1,nowGet)==1)
{
return 1;
}
sticks[i].mark = UNUSED;
return 0;
}
else if(nowLen+sticks[i].length<len)
{
sticks[i].mark = USED;
if(DFS(nowLen+sticks[i].length,nowGet,i+1)==1)
{
return 1;
}
sticks[i].mark=UNUSED;
if(nowLen==0)return 0;
for(;sticks[i].length==sticks[i+1].length&&i+1<n;i++);
}
}
}
return 0;
}
int main(){
int i;
int sum;
//scanf("%d",&n);
while(scanf("%d",&n)!=EOF&&n!=0){
for(i=0;i<MAXSIZE;i++)
{
sticks[i].mark=UNUSED;
}
sum=0;
for(i=0;i<n;i++){
scanf("%d",&sticks[i].length);
sum+=sticks[i].length;
}
//printf("???\n");
sort(sticks,sticks+n,cmp);
//printf("%d\n",sticks[0].length);
for(len=sticks[0].length;len<=sum;len++)
{
if(sum%len!=0)continue;
g=sum/len;
if(DFS(0,0,0))
{
break;
}
}
printf("%d\n",len);
}
return 0;
}
代码说明
在大神原有的代码基础上,我用algorithm中已有的排序算法代替了大神手写的冒泡排序。递归判定部分则照搬了源码。
今天也是个菜鸡啊啊啊啊,博客也没人看。
emmm,开心就好,继续加油