pku2010 Moo University - Financial Aid 二分法的高级应用

题意大概说下
N头奶牛想上大学,每个奶牛有一个SAT分数和一个助学金数目。奶牛大学只能提供M个名额以及K助学金数目。求一种分配方案使得奶牛大学录取的牛中SAT分数在中位数上的分数最大。
思路:
可以对奶牛的分数排序后二分确定中位数。开两个数组,datas,datac,前者按照奶牛分数排序,后者按照奶牛助学金数目排序。二分枚举中位数,然后进行验证:
按照datac从低到高顺序在总和小于等于k的情况下统计处落在左区间的数目left和右区间的数目right
如果left>m/2&&right>m/2,当前方案可行,尝试中位数更大的方案
如果left<m/2&&right<m/2,则不可能
如果left<m/2&&right>m/2,中点应该向右移动
如果left>m/2&&right<m/2,中点应该向左移动
注意考虑中点的覆盖情况。
还有,可能调整到最后也没法满足条件,那么也输出-1
具体看程序吧
 1 # include <cstdio>
 2 using namespace std;
 3 # include <algorithm>
 4 # include <cstring>
 5 int n,c,f;
 6 struct node
 7 {
 8    int s,c;
 9    int id;
10 }cows[100005],cowc[100005];
11 int rank[100005];
12 bool cmps(node a,node b)
13 {
14     return a.s<b.s;
15 }
16 bool cmpc(node a,node b)
17 {
18     return a.c<b.c;
19 }
20 int chk(int pos)
21 {
22     int left=0,right=0,tf=f;
23     bool mid=false;
24     for(int i=0;i<c;i++)
25       if(rank[cowc[i].id]<pos&&left<n/2)
26          if(tf>=cowc[i].c)
27             left++,tf-=cowc[i].c;
28          else break;
29       else if(rank[cowc[i].id]==pos&&!mid)
30          if(tf>=cowc[i].c)
31              mid=true,tf-=cowc[i].c;
32          else  break;
33       else if(rank[cowc[i].id]>pos&&right<n/2)
34          if(tf>=cowc[i].c)
35              right++,tf-=cowc[i].c;
36          else break;
37     if(left>=n/2&&right>=n/2&&mid) return 0;
38     else if(left>=n/2return 1;
39     else if(right>=n/2return -1;
40     else if(left<n/2&&right<n/2return -2;
41 }
42 int main()
43 {
44     scanf("%d%d%d",&n,&c,&f);
45     for(int i=0;i<c;i++)
46     {
47       scanf("%d%d",&cows[i].s,&cows[i].c);
48       cows[i].id=i;
49     }
50     memcpy(cowc,cows,sizeof(cows));
51     sort(cows,cows+c,cmps);
52     sort(cowc,cowc+c,cmpc);
53   /*  printf("sorted by s\n");
54        for(int i=0;i<c;i++)
55          printf("(%d,%d)\n",cows[i].id,cows[i].s);
56     printf("\n");
57     printf("sorted by c\n");
58        for(int i=0;i<c;i++)
59          printf("(%d,%d)\n",cowc[i].id,cowc[i].c);
60     printf("\n");*/
61     int s=n/2,e=c-1-n/2;
62     for(int i=0;i<c;i++)
63       rank[cows[i].id]=i;
64     while(s<=e)
65     {
66        int mid=(s+e)/2;
67        switch(chk(mid))
68        {
69           case -1:
70                s=mid+1;
71                break;
72           case 1:
73                e=mid-1;
74                break;
75           case 0:
76                s=mid+1;
77                break;
78           case -2:
79                printf("-1\n");
80                return 0;
81        };
82     }
83     if(chk(s-1)==0)
84       printf("%d\n",cows[s-1].s);
85     else
86       printf("-1\n");
87    //   system("pause");
88       return 0;
89 }
90 


posted on 2010-11-07 02:31 yzhw 阅读(321) 评论(0)  编辑 收藏 引用 所属分类: search


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2010年10月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

公告

统计系统

留言簿(1)

随笔分类(227)

文章分类(2)

OJ

最新随笔

搜索

积分与排名

最新评论

阅读排行榜