The 37th ACM/ICPC Asia Regional HangZhou Site Online Contest - F

来源:互联网 发布:手机网络个人理财产品 编辑:程序博客网 时间:2024/05/17 13:11

     本题通过率相当低....原因是绝大多数队都是直接贪心吧...找出A最小且B不为0的怪作为入口..可以将所有的B不为0的怪连起来...而中间的间隔可以把 B为0的怪干掉....最后再一一消灭 B 为0的怪...但这种思路是不全面的...如下列数据:

     6  20

     10  2

     10  2

   100  0

   100  0

   100  0

   100  0

    答案应该是  6  20   先打一个10  2...用2消灭两个100   0...再打一个10  2...用2消灭两个100 0...  但是如果按照裸的贪心..结果会是5  10...从10  2进入..两个10 2 连起来..有3个可用空隙...所以做出来的结果成了5  10

     那这个问题如何解决呢? 分为两方面看...若所有B不为0的怪连起来..间隔可以把B为0的都干掉..那么就是最有解了...否则的话就要做一个比较...是按原方案贪心更优..还是说将当前入口点独立出来..其B全都消灭B为0的怪物而不与后面的B不为0的怪相连.再A稍大的做入口再做更优.. .


PS:  比赛的数据太水了..感谢IsaacPei99和luyuncheng提供的数据..掐掉了我比赛时AC的代码..是有问题没考虑全面...代码已更新...


Program:

#include<iostream>#include<stdio.h>#include<algorithm>#include<string.h>#include<math.h>#include<map>#include<queue>#include<stack>#define ll long long#define oo 2000000000#define pi acos(-1)  using namespace std; struct node{    ll A,B;}p1[100055];ll n,n1,p0[100055],ss[100055];   bool cmp(node a,node b){     return a.A<b.A;}ll GetMaxNumOfDeleP0(ll m,ll n0){     int l=0,r=n0+1,mid;     while (r-l>1)     {            mid=(r+l)/2;            if (ss[mid]>m) r=mid;               else l=mid;     }     return l; }node dfs(node h,ll x,ll m,ll n0){      node q=h;     if (m<p1[x].A || x>n1) return h;     ll sum=0,i;      for (i=x;i<=n1;i++) sum+=p1[i].B-1;     sum++;         h.A+=n1-x+1;      m-=p1[x].A;     h.B+=p1[x].A;     if (sum>=n0)      {           h.A+=n0;           n0=0;      }else     {            //-----------------           q.A+=1+p1[x].B;           q.B+=p1[x].A;            q=dfs(q,x+1,m,n0-p1[x].B);          //-----------------           n0-=sum;            h.A+=sum;           i=GetMaxNumOfDeleP0(m,n0);           h.A+=i;  h.B+=ss[i];           if (q.A>h.A || q.A==h.A && q.B<h.B)  h=q;     }      return h;}int main(){      ll T,t,i,j,A,B,m,n0;    node ans,h;     scanf("%I64d",&T);    for (t=1;t<=T;t++)    {           scanf("%I64d%I64d",&n,&m);           n1=n0=0;             for (i=1;i<=n;i++)           {                  scanf("%I64d%I64d",&A,&B);                  if (B)                   {                         n1++;                          p1[n1].A=A;  p1[n1].B=B;                    }else  p0[++n0]=A;             }             sort(p1+1,p1+1+n1,cmp);            sort(p0+1,p0+1+n0);           memset(ss,0,sizeof(ss));           for (i=1;i<=n0;i++) ss[i]=p0[i]+ss[i-1];           ans.A=ans.B=0;             ans=dfs(ans,1,m,n0);             i=GetMaxNumOfDeleP0(m,n0);              h.A=i; h.B=ss[i];           if (h.A>ans.A || h.A==ans.A && h.B<ans.B)  ans=h;           printf("Case %I64d: %I64d %I64d\n",t,ans.A,ans.B);     }        return 0;}/*73 54 15 17 72 12 24 0 5 510 14 15 2110 01 03 51 0 2 03 06 2010 210 2100 0100 0100 0100 05 7 7 17 11 01 01 04 54 11 02 01 0*/