codeforces VK Cup Round 1 (online mirror)

2015-04-06 15:31:25

总结:以前做的一场,题目难度无序... 虽然时间有点久了,但是有道题必须得补!

  比赛时只做了一题(E题),而且是队友提醒的...  算是道折半搜索吧

  刚刚补了B题,一道贪心题,比赛时做出来被hack了,后来过了之后又被FST... 真是够糗的。

  

B题:

  其实就是一道贪心题... 枚举矩形的高度,然后求出在该高度下矩形的最小宽度,枚举所有可能高度后取最优解即可。

  思路很明显... (比赛时脑子实在是混... QAQ),对于当前枚举的高度,我们先扫描一遍必须“躺下”的人,并让他们躺下,如果

  必须躺下的人数大于n/2,显然该高度不符合。然后我们考虑剩下的人,如果躺下能使总宽度变小那么这个人的 w > h,躺下可以

  使宽度减少 w - h,那么我们对这些人按照(w-h)降序排序,尽量使他们躺下即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
19 #define MP(a,b) make_pair(a,b)
20 
21 typedef long long ll;
22 typedef pair<int,int> pii;
23 const int INF = (1 << 30) - 1;
24 
25 int n;
26 
27 struct node{
28     int w,h;
29 }nd[1010];
30 
31 bool cmp(node a,node b){
32     return (a.w - a.h) > (b.w - b.h);
33 }
34 
35 int main(){
36     scanf("%d",&n);
37     for(int i = 1; i <= n; ++i){
38         scanf("%d%d",&nd[i].w,&nd[i].h);
39     }
40     sort(nd + 1,nd + n + 1,cmp);
41     int ans = INF;
42     for(int h = 1; h <= 1000; ++h){
43         int cnt = 0,sum = 0;
44         bool flag = true;
45         for(int i = 1; i <= n; ++i) if(nd[i].h >= nd[i].w){ //high person
46             if(nd[i].h > h){
47                 if(nd[i].w <= h && cnt < n / 2){
48                     cnt++;
49                     sum += nd[i].h;
50                 }
51                 else{
52                     flag = false;
53                     break;
54                 }
55             }
56             else sum += nd[i].w;
57         }
58         if(flag == false) continue;
59         for(int i = 1; i <= n; ++i) if(nd[i].w > nd[i].h){ //wide person
60             if(nd[i].h > h){
61                 flag = false;
62                 break;
63             }
64             if(nd[i].w <= h && cnt < n / 2){
65                 cnt++;
66                 sum += nd[i].h;
67             }
68             else sum += nd[i].w;
69         }
70         if(flag) ans = min(ans,sum * h);
71     }
72     printf("%d\n",ans);
73     return 0;
74 }
View Code

 

E题:

  由于最多取两种,总共最多取k张(k<=20),那么不妨先取一种,取0~k张,放进map数组中,比如价值为 v 的取了 i 张,

  那么 map[v * i] = i。对于每种查询,我们只要枚举取不取第二种,如果取第二种那么取多少张,比如查询为 q,枚举第二种

  价值为 v2,取了 i2 张,我们只要找 map[q - v2 * i2] 是否存在即可,如果存在,那么记录 i2 + map[q - v2 * i2] 为当前总张数,最后取最少的总张数。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 int n,k,q,x;
28 int v[5010];
29 map<int,int> mp;
30 
31 int main(){
32     scanf("%d%d",&n,&k);
33     REP(i,n){
34         scanf("%d",&v[i]);
35         for(int j = 1; j <= k; ++j)
36             mp[v[i] * j] = j;
37     }
38     scanf("%d",&q);
39     REP(i,q){
40         int ans = INF,sum = 0;
41         scanf("%d",&x);
42         REP(j,n){
43             for(int o = 0; o <= k; ++o){
44                 if(x - o * v[j] < 0) break;
45                 if(mp[x - o * v[j]]){
46                     ans = min(ans,o + mp[x - o * v[j]]);
47                 }
48             }
49         }
50         if(ans > k) printf("-1\n");
51         else printf("%d\n",ans);
52     }
53     return 0;
54 }
View Code

 

posted @ 2015-04-06 16:07  Naturain  阅读(138)  评论(0编辑  收藏  举报