专栏文章
用深搜解决P1043
P1043题解参与者 4已保存评论 4
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @mipns9ea
- 此快照首次捕获于
- 2025/12/03 15:01 3 个月前
- 此快照最后确认于
- 2025/12/03 15:01 3 个月前
经过本蒟蒻无数次的提交,我用深搜 AC 这道题了!
解题思路
我们可以把写 个深搜,分别用来求最大值和最小值。设 表示现在要处理第 个数,上一个数字是放在第 个区块里面。那么,我们就可以很轻松地写出程序了。但是有个细节,如果 ,他也可以放在第 个区块,因为他是一个环形的。
这个程序虽然会超时,但是只有第 个数据超时了,也能获得 分的好成绩。
CPP#include<bits/stdc++.h>
using namespace std;
int n,m,a[51],sum[10],ans_max=INT_MIN,ans_min=INT_MAX;
bool flag[10];
int mod10(int x)
{
return ((x%10)+10)%10;
}
void dfs1(int id,int last)
{
int ans=1;
for(int i=1;i<=m;i++)
{
if(flag[i])
{
ans*=mod10(sum[i]);
}
}
if(id==n+1)
{
if(sum[m]!=0)
ans_min=min(ans_min,ans);
return;
}
if(id==1)
{
flag[1]=true;
sum[1]=a[1];
dfs1(2,1);
}
else
{
sum[last]+=a[id];
dfs1(id+1,last);
sum[last]-=a[id];
if((last+1)<=m)
{
sum[last+1]+=a[id];
flag[last+1]=true;
dfs1(id+1,last+1);
sum[last+1]-=a[id];
flag[last+1]=false;
}
if(id==n)
{
sum[1]+=a[n];
dfs1(n+1,1);
sum[1]-=a[n];
}
}
}
void dfs2(int id,int last)
{
int ans=1;
for(int i=1;i<=m;i++)
{
if(flag[i])
{
ans*=mod10(sum[i]);
}
}
if(id==n+1)
{
if(sum[m]!=0)
ans_max=max(ans_max,ans);
return;
}
if(id==1)
{
flag[1]=true;
sum[1]=a[1];
dfs2(2,1);
}
else
{
sum[last]+=a[id];
dfs2(id+1,last);
sum[last]-=a[id];
if((last+1)<=m)
{
sum[last+1]+=a[id];
flag[last+1]=true;
dfs2(id+1,last+1);
sum[last+1]-=a[id];
flag[last+1]=false;
}
if(id==n)
{
sum[1]+=a[n];
dfs2(n+1,1);
sum[1]-=a[n];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs1(1,0);
for(int i=1;i<=m;i++)
{
sum[i]=0;
flag[i]=false;
}
dfs2(1,0);
printf("%d\n%d",ans_min,ans_max);
return 0;
}
最优性剪枝:求最大值时,如果当前的最优可能,也不如 ,直接返回。最优可能是什么呢?就是把不确定的算出 。要注意的是,第 个要算成 ,因为它还没结束,只是开始了。第 个区块也要算成 ,因为它后面可能因第 个数字而变化。当然,我们可以用同样的方法来对求最小值的深搜剪枝。
分代码
CPP#include<bits/stdc++.h>
using namespace std;
int n,m,a[51],sum[10],ans_max=INT_MIN,ans_min=INT_MAX;
bool flag[10];
int mod10(int x)
{
return ((x%10)+10)%10;
}
void dfs1(int id,int last)
{
int ans=1,cnt=1;
for(int i=1;i<=m;i++)
{
if(flag[i])
{
if(i!=1&&i!=last)
cnt*=mod10(sum[i]);
ans*=mod10(sum[i]);
}
}
if(cnt>=ans_min)
return;
if(id==n+1)
{
if(sum[m]!=0)
ans_min=min(ans_min,ans);
return;
}
if(id==1)
{
flag[1]=true;
sum[1]=a[1];
dfs1(2,1);
}
else
{
sum[last]+=a[id];
dfs1(id+1,last);
sum[last]-=a[id];
if((last+1)<=m)
{
sum[last+1]+=a[id];
flag[last+1]=true;
dfs1(id+1,last+1);
sum[last+1]-=a[id];
flag[last+1]=false;
}
if(id==n)
{
sum[1]+=a[n];
dfs1(n+1,1);
sum[1]-=a[n];
}
}
}
void dfs2(int id,int last)
{
int ans=1,cnt=1;
for(int i=1;i<=m;i++)
{
if(flag[i])
ans*=mod10(sum[i]);
}
for(int i=1;i<=m;i++)
{
if(i==1||flag[i]==false||i==last)
cnt*=9;
else
cnt*=mod10(sum[i]);
}
if(cnt<=ans_max)
return;
if(id==n+1)
{
if(sum[m]!=0)
ans_max=max(ans_max,ans);
return;
}
if(id==1)
{
flag[1]=true;
sum[1]=a[1];
dfs2(2,1);
}
else
{
sum[last]+=a[id];
dfs2(id+1,last);
sum[last]-=a[id];
if((last+1)<=m)
{
sum[last+1]+=a[id];
flag[last+1]=true;
dfs2(id+1,last+1);
sum[last+1]-=a[id];
flag[last+1]=false;
}
if(id==n)
{
sum[1]+=a[n];
dfs2(n+1,1);
sum[1]-=a[n];
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs1(1,0);
for(int i=1;i<=m;i++)
{
sum[i]=0;
flag[i]=false;
}
dfs2(1,0);
printf("%d\n%d",ans_min,ans_max);
return 0;
}
相关推荐
评论
共 4 条评论,欢迎与作者交流。
正在加载评论...