zoukankan      html  css  js  c++  java
  • HihoCoder 1496:寻找最大值(思维DP)

    http://hihocoder.com/problemset/problem/1496

    题意:中文。

    思路:一开始做有一种想法,把所有的数都变成二进制后,最优的情况肯定是挑选所有数中最高位的1能同时有一个以上的数。

    例如样例2可以化成:

    001

    010

    100

    101

    那么肯定挑选最高位的1(第三位)并且有一个以上的数更优,如果没有一个以上那么与之后会变成0.

    那么对于这一位应该如何挑选。

    一开始想着只挑选最大的两个,但是造出下面的样例:

    1001000

    1000110

    1000110

    这样的样例显然是挑选下面的两个更优。

    于是YY出了一种想法,直接往前面扫,对于每一位的1只挑选最大的两个,然后更新答案,最后居然对了。(肯定是数据太水了)。

    A了之后想知道为什么,大概和这个有点像吧http://blog.csdn.net/ddjing_/article/details/69072023。。。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define N 101000
     4 typedef long long LL;
     5 int num[N];
     6 LL bit[21][2];
     7 
     8 int main() {
     9     int t; scanf("%d", &t);
    10     while(t--) {
    11         memset(bit, 0, sizeof(bit));
    12         int n; scanf("%d", &n);
    13         for(int i = 1; i <= n; i++) scanf("%d", &num[i]);
    14         for(int i = 1; i <= n; i++) {
    15             int tmp = num[i], cnt = 0;
    16             while(tmp) {
    17                 if(tmp & 1) {
    18                     if(bit[cnt][0] < num[i]) bit[cnt][1] = bit[cnt][0], bit[cnt][0] = num[i];
    19                     else if(bit[cnt][1] < num[i]) bit[cnt][1] = num[i];
    20                 }
    21                 cnt++; tmp >>= 1;
    22             }
    23         }
    24         LL ans = 0;
    25         for(int i = 20; i >= 0; i--) {
    26             LL now = bit[i][0] * bit[i][1] * (bit[i][0] & bit[i][1]);
    27             if(ans < now) ans = now;
    28         }
    29         printf("%lld
    ", ans);
    30     }
    31     return 0;
    32 }

    看了下别人的正解:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 #define N 100010
     5 /* 高维前缀最大次大值
     6   我们可以枚举x&y的结果z,找出两个数x&y==z使得x*y最大,更新答案即可,
     7   条件可以被削弱为z为x&y的子集,这种条件放缩不会导致最优解的丢失,
     8   z为x&y的子集等价于z为x的子集并且z为y的子集。
     9   那么我们只要找出以z为子集的最大值和次大值,然后枚举z即可计算出答案。
    10   复杂度O(k*2^k).
    11 */
    12 
    13 struct node {
    14     LL val[2];
    15     node operator + (const node &rhs) const {
    16         LL _val[2] = {val[0], val[1]};
    17         for(int i = 0; i < 2; i++)
    18             if(rhs.val[i] > _val[0]) _val[1] = _val[0], _val[0] = rhs.val[i];
    19             else if(rhs.val[i] > _val[1]) _val[1] = rhs.val[i];
    20         return (node){ _val[0], _val[1] };
    21     }
    22 } dp[(1<<20)+10];
    23 
    24 int main() {
    25     int t; scanf("%d", &t);
    26     int statu = 1 << 20;
    27     while(t--) {
    28         for(int i = 0; i < statu; i++) dp[i] = (node){0, 0};
    29         int n, a; scanf("%d", &n);
    30         for(int i = 1; i <= n; i++) scanf("%d", &a), dp[a] = dp[a] + (node){ a, 0 };
    31         for(int i = 0; i < 20; i++)
    32             for(int j = 0; j < statu; j++)
    33                 if((1 << i) & (~j)) dp[j] = dp[j] + dp[(1 << i) | j]; // 递推子集
    34                 // (1<<i) & (~j) 表示状态j没有(1<<i)这个状态的时候就更新
    35         LL ans = 0;
    36         for(int i = 0; i < statu; i++)
    37             ans = max(ans, dp[i].val[0] * dp[i].val[1] * (dp[i].val[0] & dp[i].val[1]));
    38         printf("%lld
    ", ans);
    39     }
    40     return 0;
    41 }
  • 相关阅读:
    Android Studio 单刷《第一行代码》系列 05 —— Fragment 基础
    Android Studio 单刷《第一行代码》系列 04 —— Activity 相关
    Android Studio 单刷《第一行代码》系列 03 —— Activity 基础
    Android Studio 单刷《第一行代码》系列 02 —— 日志工具 LogCat
    Android Studio 单刷《第一行代码》系列 01 —— 第一战 HelloWorld
    IDEA 内网手动添加oracle,mysql等数据源,以及server returns invalid timezone错误配置
    eclipse maven设置
    IntelliJ IDE 常用配置
    eclipse maven 常见问题解决方案
    Maven 安装和配置
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6702125.html
Copyright © 2011-2022 走看看