3.搜索、模拟

搜索、模拟

开题顺序: \(HGA\)

\(A\) luogu P1120 小木棍

  • 把能想到的剪枝加上。

    • 最终答案一定是 \(\sum\limits_{i=1}^{n}a_{i}\) 的因数。
    • 优化搜索顺序,将 \(\{ a \}\) 先降序排序,同时先选择长度尽可能长的进行拼接。
    • 猜测 \(\{ a \}\) 中会有许多重复元素,开桶或者记录上一个递归失败的匹配状态。
    • 钦定匹配顺序是递减的,减少冗余状态的搜索。
    • 剩余木棍中尝试拼接的第一根木棍递归就失败,则直接返回失败。
    • 拼接完一根木棍后恰好被拼接完整且接下来的递归失败,则直接返回失败。
    点击查看代码
    int a[70],vis[70];
    bool dfs(int pos,int n,int len,int sum,int last)
    {
    	if(pos==n+1)
    	{
    		return (sum==0);
    	}
    	else
    	{
    		int used=0;
    		if(sum==0)
    		{
    			last=0;
    			sum=len;
    		}
    		for(int i=last+1;i<=n;i++)
    		{
    			if(vis[i]==0&&sum-a[i]>=0&&a[i]!=used)
    			{
    				vis[i]=1;
    				if(dfs(pos+1,n,len,sum-a[i],i)==true)
    				{
    					return true;
    				}
    				used=a[i];
    				vis[i]=0;
    				if(sum==len||a[i]==sum)
    				{
    					break;
    				}
    			}
    		}
    		return false;
    	}
    }
    int main()
    {
    	int n,sum=0,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		sum+=a[i];
    	}
    	sort(a+1,a+1+n,greater<int>());
    	for(i=a[1];i<=sum;i++)
    	{
    		if(sum%i==0&&dfs(1,n,i,i,0)==true)
    		{
    			cout<<i<<endl;
    			break;
    		}
    	}
    	return 0;
    }
    

\(B\) luogu P2540 [NOIP2015 提高组] 斗地主 加强版

\(C\) CF58E Expression

\(D\) CF293B Distinct Paths

  • \(n-m+1>k\) 时无解,故合法状态下的 \(n,m \le 10\)

\(E\) [ABC352F] Estimate Order

\(F\) [ABC336F] Rotation Puzzle

\(G\) CF525E Anya and Cubes

  • 阶乘只需要处理到 \(18\) ,然后就是 meet in middle 板子了。

    点击查看代码
    ll a[30],jc[30],ans=0;
    unordered_map<ll,ll>f[30];
    void dfs1(ll pos,ll n,ll m,ll k,ll sum,ll num)
    {
    	if(pos==n+1)
    	{
    		f[num][sum]++;
    		return;
    	}
    	else
    	{
    		dfs1(pos+1,n,m,k,sum,num);
    		if(sum+a[pos]<=m)
    		{
    			dfs1(pos+1,n,m,k,sum+a[pos],num);
    		}
    		if(num+1<=k&&a[pos]<=18&&sum+jc[a[pos]]<=m)
    		{
    			dfs1(pos+1,n,m,k,sum+jc[a[pos]],num+1);
    		}
    	}
    }
    void dfs2(ll pos,ll n,ll m,ll k,ll sum,ll num)
    {
    	if(pos==n+1)
    	{
    		for(ll i=0;i<=k-num;i++)
    		{
    			if(f[i].find(m-sum)!=f[i].end())
    			{
    				ans+=f[i][m-sum];
    			}
    		}
    		return;
    	}
    	else
    	{
    		dfs2(pos+1,n,m,k,sum,num);
    		if(sum+a[pos]<=m)
    		{
    			dfs2(pos+1,n,m,k,sum+a[pos],num);
    		}
    		if(num+1<=k&&a[pos]<=18&&sum+jc[a[pos]]<=m)
    		{
    			dfs2(pos+1,n,m,k,sum+jc[a[pos]],num+1);
    		}
    	}
    }
    int main()
    {
    	ll n,k,m,i;
    	cin>>n>>k>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	jc[0]=1;
    	for(i=1;i<=18;i++)
    	{
    		jc[i]=jc[i-1]*i;
    	}
    	dfs1(1,n/2,m,k,0,0);
    	dfs2(n/2+1,n,m,k,0,0);
    	cout<<ans<<endl;
    	return 0;
    }
    

\(H\) luogu P9234 [蓝桥杯 2023 省 A] 买瓜

  • 为方便处理让 \(m'=2m\) ,然后就是超大背包板子了。

  • 需要适当加上最优性剪枝和优化搜索顺序。

    点击查看代码
    ll a[50],ans=0x7f7f7f7f;
    unordered_map<ll,ll>f;
    void dfs1(ll pos,ll n,ll m,ll sum,ll num)
    {
    	if(num>=ans)
    	{
    		return;
    	}
    	if(sum==m)
    	{
    		ans=min(ans,num);
    		return;
    	}
    	if(pos==n+1)
    	{
    		if(f.find(sum)==f.end())
    		{
    			f[sum]=num;
    		}
    		else
    		{
    			f[sum]=min(f[sum],num);
    		}
    	}
    	else
    	{
    		dfs1(pos+1,n,m,sum,num);
    		if(sum+a[pos]<=m)
    		{
    			dfs1(pos+1,n,m,sum+a[pos],num+1);
    		}
    		if(sum+2*a[pos]<=m)
    		{
    			dfs1(pos+1,n,m,sum+2*a[pos],num);
    		}
    	}
    	}
    	void dfs2(ll pos,ll n,ll m,ll sum,ll num)
    	{
    	if(num>=ans)
    	{
    		return;
    	}
    	if(sum==m)
    	{
    		ans=min(ans,num);
    		return;
    	}
    	if(pos==n+1)
    	{
    		if(f.find(m-sum)!=f.end())
    		{
    			ans=min(ans,f[m-sum]+num);
    		}
    	}
    	else
    	{
    		dfs2(pos+1,n,m,sum,num);
    		if(sum+a[pos]<=m)
    		{
    			dfs2(pos+1,n,m,sum+a[pos],num+1);
    		}
    		if(sum+2*a[pos]<=m)
    		{
    			dfs2(pos+1,n,m,sum+2*a[pos],num);
    		}
    	}
    }
    int main()
    {
    	ll n,m,i;
    	cin>>n>>m;
    	m*=2;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	sort(a+1,a+1+n);
    	dfs1(1,n/2,m,0,0);
    	dfs2(n/2+1,n,m,0,0);
    	cout<<(ans==0x7f7f7f7f?-1:ans)<<endl;
    	return 0;
    }
    

\(I\) POJ1475 Pushing Boxes

\(J\) UVA589 Pushing Boxes

posted @ 2024-10-08 19:08  hzoi_Shadow  阅读(33)  评论(0编辑  收藏  举报
扩大
缩小