社区讨论
关于此题复杂度
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 条回复,欢迎继续交流。
正在加载回复...