zoukankan      html  css  js  c++  java
  • ZZULIOJ 1921: B 【dp + 位运算】

    1921: B

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 270  Solved: 31

    Description

    给定一个长度为n的数字序列a,从中选取一个长为m的子序列b满足 b[i]&b[i-1]!=0 (2<=i<=m)
    求最大的m。

    Input

    第一行输入一个整数t,代表有t组测试数据。
    每组数据第一行输入一个整数n代表a序列的长度,接下来一行输入n个正整数表示ai(0<i<=n)。
    1<=t<=20,0<=n<=100000,0<=ai<=1e9。

    Output

    一个整数表示最大的m。

    Sample Input

    1
    3
    1 1 1

    Sample Output

    3

    HINT

     

    Source

    这道题让我一脸懵逼状(⊙﹏⊙)b。又读错题了。。。。我以为是所有子列按位与运算。。。。我说怎么各种WA。。我说为嘛还要dp。。。。。

    思路:

    用dp记录当前状态下的每一位的最大值,对于序列中的元素, 如果这个数的第j为1, 他肯定要和前面的接上,这样就保证了他和相邻的按位与不为零,然后dp的值等于他后面的加上一。每次检查他的每一位的二进制状态,更新最值。

    对于一维的转移方程为 for  dp【i】 = max(dp【last】 + 1, dp【i】); 

    #include <bits/stdc++.h>
    using namespace std;
    const int BIT = 32;
    const int maxm = 100000 + 10;
    int a, dp[maxm], last[40];
    void init() {
        memset(dp, 0, sizeof(dp));
        memset(last, 0, sizeof(last));
    }
    bool judge_bit(int x, int y) {
        if (x & (1<<y)) return true;
        return false;
    }
    int main() {
        int n, t;
        scanf("%d", &t);
        while(t--) {
            int ans = 0; scanf("%d", &n); init();
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a);
                for(int j = 0; j <= BIT; j++) {
                    if(judge_bit(a, j)) {
                        dp[i] = max(dp[last[j]] + 1, dp[i]);
                        //last记录的是上一次 j 位为 1的位置
                        last[j] = i;
                    }
                }
                ans = max(ans, dp[i]);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }


  • 相关阅读:
    最好的 6 个 HTML5 的多媒体播放器
    原型开发、模型构建和设计反馈在线工具
    让Xcode 4.2生成的app支持旧版iOS设备(armv6)
    TOUCHXML解析xml
    50 个最佳 CSS3 教程大放送
    十八般武艺!移动应用开发者必备的18款利器
    ios开源程序集
    iOS如何隐藏各种bar
    读书笔记之:C语言教程(C程序设计第三版)——清华大学
    JM8.6中帧内帧间模式的选择
  • 原文地址:https://www.cnblogs.com/cniwoq/p/6770811.html
Copyright © 2011-2022 走看看