社区讨论

关于此题复杂度

P1120[CERC 1995] 小木棍参与者 6已保存回复 22

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
22 条
当前快照
1 份
快照标识符
@mkgvmv6y
此快照首次捕获于
2026/01/16 20:50
上个月
此快照最后确认于
2026/01/19 09:15
上个月
查看原帖
本题的搜索算法是否可以证明时间复杂度是一个伪多项式?
发现好像对于每一种状态的排列组合至多搜索一次。
这是本人代码CPP
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
#undef INT_MAX
#define INT_MAX 2147483647
int n,a_bucket[151],max_stick=-INT_MAX,min_stick=INT_MAX,sum,ans;
bool dfs
(int rest/*还剩多少根*/,
int now/*现在拼了多少*/,
int len/*总长*/,
int max_can_used/*现在可以用的最长木棍*/)
{
    if(!rest)
    {
        ans=len;
        return true;
    }//成功
    if(now==len)
    {
        return dfs(rest-1,0,len,max_stick);
    }
    for(int /*长一点的木棍试过了,行就不会回溯了*/i=max_can_used;i>=min_stick;i--)
    {
        if(a_bucket[i]&&now+i<=len/*还剩,拼上去不会超*/)
        {
            a_bucket[i]--;
            if(dfs(rest,now+i,len,i))
            {
                a_bucket[i]++;
                return true;
            }//从最大的开始看行不行
            a_bucket[i]++;
            if(now+i==len||now==0)
                break;//拼新木棍或者拼完木棍都不行,肯定是前面错了
        }
    }
    return false;
}
int main()
{
    scanf("%d",&n);
    for(int i=1,a=0;i<=n; i++)
    {
        scanf("%d",&a);
        if(a>50)
        {
            continue;
        }
        sum+=a;
        a_bucket[a]++;
        max_stick=max(max_stick,a);
        min_stick=min(min_stick,a);
    }
    for(int len=min_stick;len*2<=sum;len++)
    {
        if(sum%len)//不整除
            continue;//不行
        if(dfs(sum/len,0,len,max_stick))
        {
            cout<<ans<<endl;
            return 0;
        }
    }
    printf("%d\n",sum);//其他不行只能全拼一起
    return 0;
}

回复

22 条回复,欢迎继续交流。

正在加载回复...