算法学社
記錄難忘的征途
posts - 141,comments - 220,trackbacks - 0
涨了111 rating 真是耗rp啊.....

300pt

    有一个1到N(N<50)的排列,序列中的一些数被隐藏了(表示为0)。你每一次都可以选择数列中某个位置的一个数作为自己的得分,不论这个数是否被隐藏,你都会得到相应的分数。
    请问最少取多少个数能保证人品最坏的情况下至少拿到P(P<1,000,000)分。

思路分析

    因为RP总是很差,所以拿到被隐藏的数的时候是从最小开始拿的。如果每次都拿被隐藏的数的话,肯定是从小到大的一圈一圈的拿。
    如果拿没被隐藏的数的话,那么直接拿最大的就好了。
    于是算法和去年上海regional第一题就一样一样了.... 前面要么一圈一圈拿被隐藏的数,要么都拿最大的数。
    这个是贪心的。
    最后P会剩一个余数。
    暴力判断是拿最大的还是拿被隐藏的(2选1,交叉着来是不可能的...)。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<vector>
 5 #include<cstring>
 6 using namespace std;
 7 #define re(i,n) for(int i=0;i<n;i++)
 8 #define re1(i,n) for(int i=1;i<=n;i++)
 9 #define re2(i,n) for(int i=0;i<=n;i++)
10 #define re3(i,n) for(int i=1;i<n;i++)
11 #define clr(a,n) memset(a,n,sizeof(a))
12 template <typename T> inline T chkmin(T& a,T b){ return a > b ? a = b : a ; }
13 template <typename T> inline T chkmax(T& a,T b){ return a < b ? a = b : a ; }
14 int hash[100];
15 int cal(int P,int mx){
16     if(!mx) return ~0u>>2;
17     return P/mx + (P%mx >0);
18 }
19 int cal(int P,vector<int> num){
20     sort(num.begin(),num.end());
21     int sum =0;
22     re(i,num.size()) {
23         sum+=num[i];
24         if(sum >= P) return i+1;
25     }
26     return ~0u>>2;
27 }
28 class BlurredDartboard{
29     public :
30     int minThrows(vector <int> num, int P){
31         int n = num.size(),mx = 0;
32         re(i,n){
33             hash[num[i]] = 1;
34             chkmax(mx,num[i]);
35         }
36         vector <int> temp;
37         re1(i,n) if(!hash[i]) temp.push_back(i);
38         int m = temp.size(),suma = 0;
39         re(i,m) suma += temp[i];
40         if(!m) m = 1;
41         int sumb =  mx*m;
42         int sum= max(suma,sumb);
43         int ans = P/sum*m;
44         cout<<ans<<endl;
45         P %=sum;
46         if(P==0) return ans;
47         int a = cal(P,mx);
48         int b = cal(P,temp);
49         return ans + min(a,b);
50     }
51 };
52 

550pt

    有N(N<50)本书,每本书都有一个价值w[i]。现在有M次操作,每次操作i(i=0 mod 2),小A可以从自己的书包拿出书向小B的书包里放最多move[i]本书。
    每次操作j(j=0 mod 1),小B可以从自己书包往小A书包里放最多move[j]本书。
    第一次操作,小A要从书堆中拿出move[0]本书装到B的书包中。
    最后,小A的书包中书的总价值为Wa,小B为Wb。小A想让Wb-Wa最大, 小B相让Wa-Wb最大.
    假设二个人都足够聪明.... 输出最后的Wa和Wb。
    如果有多种选择,那么输出Wa+Wb最大的那种可能。

思路分析

    没敲完... 残念啊... 我果然还是弱阿....
    显然除了第一步从书堆里放书意外,一旦书包中的书确定了,两人都是贪心的拿书。
    问题就是从书堆中拿哪些书...... DP就可以了吧....(ms有更简单的??)
    update: 下午闲着没事,就敲完了,可以去吃饭了(ms当时就是写完了也进不了前50.... 还是弱 阿....)
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 using namespace std;
 7 int hash[100];
 8 void work(vector<int> B,vector<int> num){
 9     vector<int> A;
10     for(int i=1; i< num.size();i++){
11         if(i&1){
12             sort(B.begin(),B.end());
13             int n = B.size();
14             int m = min(n,num[i]);
15             for(int j = n-1; j>= n-m; j--){
16                 A.push_back(B[j]);
17                 B.erase((vector<int>::iterator)&B[j]);
18             }
19         }
20         else {
21             sort(A.begin(),A.end());
22             int n = A.size();
23             int m = min(n,num[i]);
24             for(int j = n-1; j>= n-m; j--){
25                 B.push_back(A[j]);
26                 A.erase((vector<int>::iterator)&A[j]);
27             }
28         }
29     }
30     for(int i=0;i<A.size();i++) hash[A[i]] = -1;
31     for(int i=0;i<B.size();i++) hash[B[i]] = 1;
32 }
33 const int inf = ~0u>>2;
34 int dp[100][100],P[100][100];
35 class HeavyBooks{
36     public : vector <int> findWeight(vector<int> book,vector <int> mv){
37         vector<int> temp;
38         sort(book.begin(),book.end());
39         int n =book.size();
40         int m = min(mv[0],n);
41         for(int i =0; i<m;i++) temp.push_back(i);
42         work(temp,mv);
43     //    for(int i=0;i<m;i++) cout<<hash[i]<<" "; cout<<endl;
44         for(int j=0;j<m;j++)
45             for(int i=j;i<n;i++)
46                 if(i == j){
47                     P[i][j] = i-1;
48                     dp[i][j] =(i ? dp[i-1][j-1]:0) + hash[j] * book[i];
49                 }
50                 else if(j == 0){
51                     dp[i][0] = hash[0] * book[i];
52                     P[i][0] = -1;
53                 }
54                 else {
55                     int mx = -inf,s;
56                     for(int k = i-1; k>=j-1;k--)
57                         if(dp[k][j-1] > mx){
58                             s = k; mx = dp[k][j-1];
59                         }
60                     dp[i][j] = hash[j] * book[i] + mx;
61                     P[i][j] = s;
62                 }
63         int mx = -inf,s;
64         for(int i=n-1; i>=m-1;i--)
65             if(dp[i][m-1]>mx){
66                 s = i;
67                 mx = dp[i][m-1];
68             }
69         int A = 0, B = 0;
70         for(int i=m-1;i>=0;i--){
71             //cout<<s<<endl;
72             if(hash[i]>0) B += book[s]; else A += book[s];
73             s = P[s][i];
74         }
75         temp.clear();
76         temp.push_back(A);
77         temp.push_back(B);
78         return temp;
79     }
80 };
81 
posted on 2012-05-13 08:47 西月弦 阅读(336) 评论(0)  编辑 收藏 引用 所属分类: 比赛感言

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理