UVA307 Sticks

题意:一组等长的木棒,将它们随机的砍掉,得到若干根小木棍,

   每一节小棍的长度都不超过50个单位。然后想把这些木棍拼接起来,恢复到裁剪前的状态,

   但忘记了初始时有多少木棒以及木棒的初始长度。计算木棒的可能最小长度,每一节木棍的长度都用大于零的整数表示。

  输入包含多组数据

这题很经典(有毒啊)

首先,对所有木棍排序(便于搜索)

然后倒着枚举初始木棒个数, 可以通过求平均算出木棒长度(最短),有解就输出(最优)

若当前个数无法被平均分,false

若当前答案比最长木棍小,false

然后开始搜索

详见代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define love_nmr 0
int n;
int stick[100];
int ans;
int ave;
bool vis[100];
inline bool dfs(int num,int pos,int len)
{
    if(num==n+1)return true;          //全部搜完(合法了)
    for(int i=pos;i<=n;i++)            
    {
        if(vis[i]) continue;             //被用过 
        if(stick[i]+len<ans)              //接上也比ans小(可用)
        {
            vis[i]=true;
            if(dfs(num+1,i+1,len+stick[i])) return true;    //接上继续搜(标记)
            vis[i]=false;
            while(stick[i]==stick[i+1]&&i+1<=n)i++;       //有跟他一样的跳过
        }
        else if(stick[i]+len==ans)                 //正好接上
        {
            vis[i]=true;
            if(dfs(num+1,1,0)) return true;           //下一次从头开始
            vis[i]=false;
            return false;
        }
        if(!len)return false;          //没有能跟它拼的
    }
    return false;
}
inline bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        ave=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&stick[i]);
            ave+=stick[i];
        }
        sort(stick+1,stick+n+1,cmp);
        for(int i=n;i>=0;i--)
        {
            if(ave%i==0&&(ave/i)>=stick[1])
            {
                ans=ave/i;
                // cout<<ans<<endl;
                memset(vis,0,sizeof vis);
                if(dfs(1,1,0))
                {
                    printf("%d\n",ans);
                    break;
                }
            }
        }
    }
    return love_nmr;
}

猜你喜欢

转载自www.cnblogs.com/olinr/p/9426933.html