zoukankan      html  css  js  c++  java
  • SRM 548 DIV2

    本来早就该写的,一直拖到现在。

    第一题应该算是很水的题,就是数字的种类乘以某种数字出现的最大次数。

    http://community.topcoder.com/stat?c=problem_solution&rm=313611&rd=15170&pm=11985&cr=23038076

    第二题比赛期间没有想到,后来看来一下别人的,原来用二分法就可以搞定了

     1 #include <iostream>
     2 #include <string>
     3 #include <vector>
     4 #include <cstdlib>
     5 #include <map>
     6 #include <algorithm>
     7 #include <cmath>
     8 using namespace std;
     9 class KingdomAndTrees{
    10 public:
    11     bool valid(vector <int> heights,int l,int n){
    12         heights[0]=max(heights[0]-l,1);
    13         for(int i=1;i<n;i++){
    14             if(heights[i]<=heights[i-1])
    15                 heights[i]=min(heights[i-1]+1,heights[i]+l);
    16             else
    17                 heights[i]=max(heights[i-1]+1,heights[i]-l);
    18 
    19             if(heights[i]<=heights[i-1])
    20                 return false;
    21         }
    22         return true;
    23 
    24     }
    25     int minLevel(vector <int> heights){
    26         int left=0;
    27         int right=1000000000;
    28         int mid;
    29         int n=heights.size();
    30         int exists=0;
    31         while(left<right){
    32             mid=(left+right)/2;
    33             if(valid(heights,mid,n)){
    34                 right=mid;
    35                 exists=1;
    36             }else{
    37                 left=mid+1;
    38             }
    39         }
    40 
    41         return left;
    42     }
    43 };

    第三题则悲催了,用的穷举法加剪枝,明显不行,第五个测试用例就超时了,就没有提交,据说是用的DFS,还没有看大牛的代码。

    topcoder wiki 的答案,加上了自己的一点注释,自己真心想不出来啊.....

      1 #define FOR(x,a,b) for (int x = a; x <= b; x++)
      2 int f[(1 << 17) + 10][18][2];
      3 int n, cs[17], res[17], old[17];
      4 vector<int> rt;
      5 
      6 //s store information about wich digits is used
      7 //i is the position that we have to dicide which digits to push in
      8 //ok = 1 min the i + 1 digits prefix of the password is strictly less than the 
      9 //i + 1 digits prefix of oldpassword
     10 //f[s][i][ok] = 1 mean we can continue bulding the password that strictly less than oldpassword
     11 int lower(int s, int i, int ok) {
     12     if (f[s][i][ok] != -1)//假如已经计算出来了
     13         return f[s][i][ok];
     14     if (i == n) {
     15         f[s][i][ok] = ok;//备忘录
     16         return ok;
     17     }
     18 
     19     f[s][i][ok] = 0;
     20     FORD(j, n - 1, 0)//因为是选取小于原数字的最大值,所以倒着选
     21     if ((s & (1 << j)) == 0 //第j位还没有使用
     22             && cs[j] != rt[i]//不是限制的数字
     23             && (ok == 1 || cs[j] <= old[i]))//已经严格小或者当前位<=原来的
     24         if (lower(s | (1 << j),//使用第j位 
     25                 i + 1, //计算后边的
     26                 ok | (cs[j] < old[i]))) //填加第j位后是否<原来的
     27         {
     28             f[s][i][ok] = 1;
     29             return 1;
     30         }
     31 
     32     return 0;
     33 }
     34 
     35 //find the maximum password in all passwords that less than oldpassword
     36 void find_lower(int s, int i, int ok) {
     37     if (i == n)
     38         return;
     39 
     40     FORD(j, n - 1, 0)
     41     if ((s & (1 << j)) == 0 &&//某一位还没有选
     42             cs[j] != rt[i] &&//不是限制条件
     43             (ok == 1 || cs[j] <= old[i]))//判断是否可以用这个数字
     44         if (lower(s | (1 << j), i + 1, ok | (cs[j] < old[i]))) {
     45             res[i] = cs[j];
     46             find_lower(s | (1 << j), i + 1, ok | (cs[j] < old[i]));
     47             return;
     48         }
     49 }
     50 
     51 //funtion upper and find_upper is similar with lower and find_lower
     52 int upper(int s, int i, int ok) {
     53     if (f[s][i][ok] != -1)
     54         return f[s][i][ok];
     55     if (i == n) {
     56         f[s][i][ok] = ok;
     57         return ok;
     58     }
     59 
     60     f[s][i][ok] = 0;
     61     FOR (j, 0, n - 1)
     62         if ((s & (1 << j)) == 0 && cs[j] != rt[i]
     63                 && (ok == 1 || cs[j] >= old[i]))
     64             if (upper(s | (1 << j), i + 1, ok | (cs[j] > old[i]))) {
     65                 f[s][i][ok] = 1;
     66                 return 1;
     67             }
     68     return 0;
     69 }
     70 
     71 void find_upper(int s, int i, int ok) {
     72     if (i == n)
     73         return;
     74 
     75     FOR (j, 0, n - 1)
     76         if ((s & (1 << j)) == 0 && cs[j] != rt[i]
     77                 && (ok == 1 || cs[j] >= old[i]))
     78             if (upper(s | (1 << j), i + 1, ok | (cs[j] > old[i]))) {
     79                 res[i] = cs[j];
     80                 find_upper(s | (1 << j), i + 1, ok | (cs[j] > old[i]));
     81                 return;
     82             }
     83 }
     84 
     85 long long newPassword(long long oldPassword, vector<int> restrictedDigits) {
     86     n = 0;
     87     LL tg = oldPassword;
     88     while (tg) {
     89         cs[n++] = tg % 10;
     90         tg /= 10;
     91     }
     92 
     93     //old store digits of oldPassword from left to right
     94     //cs store digits of oldPassword in non-decrease order 
     95     FOR (i, 0, n - 1)
     96         old[i] = cs[n - 1 - i];
     97     sort(cs, cs + n);
     98 
     99     rt = restrictedDigits;
    100     //FOR (i, 0, n - 1) cout << old[i] << " " << cs[i] << " " << rt[i] << endl;
    101 
    102     //if the new password can be same as the old one, return it
    103     int ok = 1;
    104     FOR (i, 0, n - 1)
    105         if (old[i] == rt[i])
    106             ok = 0;
    107     if (ok)
    108         return oldPassword;
    109 
    110     LL a, b;
    111     a = b = -1;
    112 
    113     //find a is the maximum password that less than the oldPassword
    114     SET(f, -1);
    115     if (lower(0, 0, 0)) {
    116         find_lower(0, 0, 0);
    117         a = 0;
    118         FOR (i, 0, n - 1)
    119             a = a * 10 + res[i];
    120     }
    121 
    122     //find b is the minimum password that greater than the oldPassword
    123     SET(f, -1);
    124     if (upper(0, 0, 0)) {
    125         find_upper(0, 0, 0);
    126         b = 0;
    127         FOR (i, 0, n - 1)
    128             b = b * 10 + res[i];
    129     }
    130 
    131     //decide a or b is the result
    132     if (a == -1)
    133         return b;
    134     if (b == -1)
    135         return a;
    136 
    137     if (abs(a - oldPassword) > abs(b - oldPassword))
    138         return b;
    139     if (abs(a - oldPassword) < abs(b - oldPassword))
    140         return a;
    141 
    142     return a;
    143 
    144 }
  • 相关阅读:
    windows7 gvim 配置(好用)
    程序员的惰性
    java性能提升
    spring cloud gateway 负载均衡流程
    广告业务
    mysql二进制binarylog监控服务
    虽然垃圾,以后用得到在翻一翻,优化下
    hash冲突后处理
    jdk1.6乃至1.7中的Iepoll空轮询bug,netty中是怎样解决的
    树形结构
  • 原文地址:https://www.cnblogs.com/kakamilan/p/2580201.html
Copyright © 2011-2022 走看看