Evil Book -- CodeChef

传送门

分析

对于这道题,我们首先思考一个贪心策略,即对于所有我们要打败的厨师我们肯定可以先打败需使用帮助次数少的厨师再打败需使用帮助次数多的厨师 ,因为这样可以使得能支付得起帮助费用的可能性尽可能的大。在确定顺序之后我们便可以进行dfs啦,只需要在搜索过程中加一些可行性剪枝和最优性剪枝就行了。

代码

#include<bits/stdc++.h>
using namespace std;
#define li long long
const li inf = 1e12+7;
int w[110],c[110],n,x,used[110];
double pw[110];
li ans=inf,all;
inline void dfs(int k,int wh,double m,double sum){
      if((li)(sum+0.5)>=ans)return;
      if(m>=666){
        ans=(li)(sum+0.5);
        return;
      }
      if(m<double(k)*double(x))return;
      if(m+double(all)/pw[k]<666)return;
      for(int i=wh;i<=n;i++)
       if(!used[i]&&double(w[i])/pw[k]>double(k)*x){
          used[i]=1;all-=w[i];
          dfs(k,i,m+double(w[i])/pw[k]-double(k)*x,sum+c[i]/pw[k]);
          used[i]=0;all+=w[i];
        }
      dfs(k+1,1,m,sum);
}       
int main(){
      int i,t;
      pw[0]=1;
      for(i=1;i<=20;i++)pw[i]=pw[i-1]*3;
      scanf("%d",&t);
      while(t--){
          memset(used,0,sizeof(used));
          scanf("%d%d",&n,&x);
          ans=inf;all=0;
          for(i=1;i<=n;i++){
            scanf("%d%d",&c[i],&w[i]);
            all+=w[i];
        }
          dfs(0,1,0,0);
          if(ans==inf)puts("impossible");
            else printf("%lld\n",ans);
      }
      return 0;
}
posted @ 2018-07-25 14:37  水题收割者  阅读(595)  评论(0编辑  收藏  举报