nyoj293(Sticks)

来源:互联网 发布:免费听英语的软件 编辑:程序博客网 时间:2024/05/19 04:53

nyoj293(Sticks)

题目大意:给定一定数量的小木棍,要求拼成m根长度相同的棍子(所有小棍都要使用)

输出拼成的棍子的长度(L)

1.解题思路(确定算法)

(1)既然要拼成长度相同的棍子,那么所有小木棍的长度和一定能被目标长度(L)整除

(2)拼棍子自然要一个一个去试,如果试着试着无法拼成,就要换掉上一根小木棍(回溯)

所以就会想到使用(深度优先搜索)

2.解题思路(剪枝与优化)

(1)优化:如果盲目的去拼棍子,必定会浪费时间,那么首先就要确定拼成多长的棍子

除了思路1.(1)还要选择从最长的小木棍开始,因为如果选择短的开始作为目标长度

那么一旦出现比目标长度还长的小木棍,那么前面的搜索就白费了.所以就先把

提供的小木棍按从大到小(从小到大)排好序,最大的木棍(依次加一)开始确定

(2)剪枝:这个题目的剪枝比较多,有些不好理解,差了很多资料才明白

1.考虑当前小木棍拼接失败,那么是否还有必要去试与当前小木棍相同的

2.考虑(当前需要长度=目标长度),在进行一次递归后如果无法拼接成功

    那么就没必要去试以后的棍子,因为长的棍子都无法拼接成功,比它短的

    更无法拼接成功

3.同2类似,如果(当前需要长度=当前小木棍长度)而以后拼接失败,不要在试其他的

   为什么?因为即便后面可以替代当前木棍(当前小木棍长度=(后续代替)),但是还是会失败,

   所以抛弃这次查找,返回(3理解模糊,答题意思理解)

   ----------------------------------------------------------------------------------------------------------------------------    

源码

 #include <stdio.h>#include <memory.h>#include <algorithm>using namespace std;int sticks[64];char vis[64];int leng, countStick, n;bool flag;bool dfs(int cur, int num, int need){    if (need == 0)//(1)      //find one stick    {        need = leng;    // reset        num++;          // add the sticks's count        cur = n-1;      // from head to search    }                            // mustn't exchange 'if(1) and if(2)'    if (num == countStick)//(2)        return true;    // sucess    for (int i=cur; i>=0; --i)    {        if (!vis[i])        {            if (need>=sticks[i])            {                vis[i] = 1;                if (dfs(i-1, num, need-sticks[i]))                    return true;                vis[i] = 0;                if (need == leng)    //剪枝(一个也无法匹配)                    return false;                if (need == sticks[i])    //剪枝(往后匹配失败)                    return false;                while (i-1>=0 && sticks[i-1] == sticks[i])    //剪枝(去掉相同)                    i--;            }        }    }    return false;}int main(){    int sum;    while (scanf("%d", &n), n)    {        sum = 0;        for (int i=0; i<n; ++i)        {            scanf("%d", &sticks[i]);            sum += sticks[i];        }        sort(sticks, sticks+n);//优化        leng = sticks[n-1];        for (; leng<=sum; ++leng)            if (sum % leng == 0)            {                countStick = sum / leng;                memset(vis, 0, sizeof(vis));                if (dfs(n-1, 0, leng))            {            break;            }            }        printf("%d\n", leng);    }    return 0;}        









原创粉丝点击