codevs1005生日礼物
Posted 那一抹落日的橙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs1005生日礼物相关的知识,希望对你有一定的参考价值。
这个题直接爆搜显然很好想,但是直接爆搜而不剪枝的话最坏复杂度应该是6^10*10,显然会爆炸。开始我并没有想到怎么剪枝,因此只拿了80,看过题解后恍然大悟:我们可以提前处理好第i种本子之后所有的本子每种纸最多还能用多少,搜索的时候,如果发现某种颜色的纸,就算之后所有的该种颜色的纸全部用上都无法超越现在的最大值,则退出
#include<iostream> #include<cstring> #include<cstdio> using namespace std; inline void re(int &a) { a=-0; char b=getchar(); while(b<‘0‘||b>‘9‘) b=getchar(); while(b>=‘0‘&&b<=‘9‘) a=a*10+b-‘0‘,b=getchar(); } int n,m,s[20],ben,sum[12][12],a[12][12],bi[12],cun[20],ans=1000; void dfs(int tot,int ceng)//tot记录买了多少个本子,ceng记录现在判断到第几种本子了 { bool flag=0; for(int i=2;i<=m;i++) { if(s[i]==0||s[i]!=s[i-1]||s[i]>ans||s[i-1]>ans) { flag=1;break; } } if(flag==0) { ans=min(ans,s[1]);return; } if(tot==ben||ceng==n) return; int mx=0; for(int i=1;i<=m;i++) mx=max(mx,s[i]); for(int i=1;i<=m;i++)//如果我们发现,就算把下面的所有本子都买了,也不能追上现在的最大值,直接停止 { if(mx>s[i]+sum[ceng+1][i]) return; } for(int i=0;i<=bi[ceng+1];i++)//枚举这种本子买几个 { for(int j=1;j<=m;j++) s[j]+=a[ceng+1][j]*i; cun[ceng+1]=i; dfs(tot+i,ceng+1); for(int j=1;j<=m;j++) s[j]-=a[ceng+1][j]*i; cun[ceng+1]=0; } } int main() { re(n),re(m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) re(a[i][j]); for(int i=1;i<=n;i++) re(bi[i]),ben+=bi[i]; for(int i=n;i>=1;i--)//我们可以通过提前算出每种本子下面每种纸还有多少可以用的,以此来帮助剪枝 for(int j=m;j>=1;j--) sum[i][j]=sum[i+1][j]+a[i][j]*bi[i]; dfs(0,0); if(ans*m<=1000) cout<<ans*m; else cout<<"alternative!"; }
以上是关于codevs1005生日礼物的主要内容,如果未能解决你的问题,请参考以下文章