1. 程式人生 > >【codevs1005】生日禮物

【codevs1005】生日禮物

lte 發現 getchar() std 最大 提前 ++ har 所有

這個題直接爆搜顯然很好想,但是直接爆搜而不剪枝的話最壞復雜度應該是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】生日禮物