P1120 小木棍 [数据加强版]

题目描述

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过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 ;
        }

    }



}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值