题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入输出格式
输入格式:
共二行。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65N≤65
(管理员注:要把超过5050的长度自觉过滤掉,坑了很多人了!)
第二行为NN个用空个隔开的正整数,表示NN根小木棍的长度。
输出格式:
一个数,表示要求的原始木棍的最小可能长度
输入输出样例
输入样例#1: 复制
9 5 2 1 5 2 1 5 2 1
输出样例#1: 复制
6
说明
2017/08/05
数据时限修改:
-#17 #20 #22 #27 四组数据时限500ms500ms
-#21 #24 #28 #29 #30五组数据时限1000ms1000ms
其他时限改为200ms200ms(请放心食用)
都不想活了。
#include<stdio.h>
#include<functional>
#include<queue>
#include<vector>
#include<iostream>
#include<sstream>
#include<string.h>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int num[500010],maxn,minn,sum;
int max(int x,int y) {
return x>y?x:y;
}
int min(int x,int y) {
return x>y?y:x;
}
void dfs(int wait,int already,int need,int can) { //从前往后依次为 还需要拼凑得到的木棍数量
int i; // 当前已经拼凑得到的木棍的长度
if(wait==0) { //如果已经完成所有的木棍的拼凑,则直接输出结果 需要得到的木棍的长度
printf("%d",need); // 当前可以使用的最长木棍的长度
exit(0);
}
if(already==need) { //如果当前拼凑出的木棍的长度等于需要得到的木棍的长度,则开始拼凑下一根
cout<<wait<< "----------------"<<endl;
dfs(wait-1,0,need,maxn);
return ;
}
for(i=can; i>=minn; i--)
if(num[i] && i+already<=need) {
num[i]--;
cout<<" level "<<wait<<" select "<<i<<" num"<<num[i]<<endl;
dfs(wait,already+i,need,i);
num[i]++;
if(already==0 || already+i==need)
return ;
}
}
int main() {
// freopen("in.txt","r",stdin);
int i,j,k,m,n,temp;
scanf("%d",&n);
for(i=1; i<=n; i++) {
scanf("%d",&k);
if(k<=50) { //忽略长度小于等于50的木棍
sum+=k;
num[k]++;
minn=min(k,minn);
maxn=max(k,maxn);
}
}
temp=sum/2;
for(i=maxn; i<=temp; i++) //枚举每一种可能选定的长度
if(sum%i==0)
dfs(sum/i,0,i,maxn);
printf("%d",sum);
return 0;
}
我的代码:
#include<stdio.h>
#include<functional>
#include<queue>
#include<vector>
#include<iostream>
#include<sstream>
#include<string.h>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
int N;
int n,nn;
int imax,imin;
int val;
queue<int> que;
bool isgoon=true;
vector<int> len,num,num2;
void dfs(int ilevel,int anum);
int main() {
cin>>N;
int t;
imax=1;
imin=100;
n=0;
int sum=0,pre=-1;
vector<int> vtemp(N,0);
for(int i=0; i<N; i++)
{
cin>>vtemp[i];
}
sort(vtemp.begin(),vtemp.end());
int kk=0;
for(int i=0; i<N; i++)
{
t=vtemp[i];
if(t<=50)
{
if(t==pre)
num[kk-1]++;
else
{
num.push_back(1);
len.push_back(t);
pre=t;
kk++;
}
imax=max(imax,t);
imin=min(imin,t);
sum+=t;
}
}
cout<<sum<<endl;
cout<<kk<<endl;
for(int i=0; i<kk; ++i)
cout<<"key: "<<len[i]<<" value: "<<num[i]<<endl;
while(imax<=sum)
{
if((double)sum/imax==sum/imax)
{
que.push(imax);
}
imax++;
}
int testn=que.size();
num2.resize(kk);
for(int i=0; i<testn; i++)
{
val=que.front();
que.pop();
nn=sum/val;
for(int j=0; j<num.size(); j++)
num2[j]=num[j];
dfs(0,val);
if(!isgoon)
{
cout<<val<<endl;
return 0;
}
}
}
void dfs(int ilevel,int anum)
{
if(!isgoon) return;
//cout<<" level "<<ilevel<<" need "<<anum<<endl;
if(ilevel==nn)
{
isgoon=false;
return;
}
if(anum==0)
{
cout<<ilevel<< "----------------"<<endl;
dfs(ilevel+1,val);
return;
}
for(int i=len.size()-1; i>=0; --i)
{
if(len[i]>anum) continue;
if(num2[i]<=0)
{
continue;
}
int leftval=anum-len[i];
{
num2[i]--;
//if(leftval>=imin)
{
cout<<" level "<<ilevel<<" select "<<len[i]<<" num"<<num2[i]<<endl;
dfs(ilevel,leftval);
}
num2[i]++;
if(leftval==anum||leftval==0)
return ;
}
}
}