首页 > 其他分享 >洛谷题单指南-动态规划2-P4310 绝世好题

洛谷题单指南-动态规划2-P4310 绝世好题

时间:2024-05-09 17:36:08浏览次数:28  
标签:maxx 二进制位 int 洛谷题 好题 P4310 序列 长度 dp

原题链接:https://www.luogu.com.cn/problem/P4310

题意解读:求最长的子序列长度,使得每相邻两个元素 & 操作不为0。

解题思路:

直观来看,可以通过类似最长上升子序列的算法,进行状态转移,但是复杂度为O(n^2),会超时

状态表示:dp[i]表示前i个数能产生满足条件的子序列的最长长度

状态转移:dp[i] = max(dp[1] + 1, dp[2] + 1, ... , dp[i-1] + 1)

初始值:dp[i] = 1

结果:max(dp[i])

90分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;
int n;
int a[N];
int dp[N]; //dp[i]表示前i个数能产生满足条件的子序列的最长长度
int ans;

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];

    for(int i = 1; i <= n; i++)
    {
        dp[i] = 1;
        for(int j = 1; j < i; j++)
        {
            if(a[i] & a[j]) //注意:如果要写成不等于0判断,(a[i]&a[j]) != 0要加括号才能作为整体计算,因为&优先级较低
            {
                dp[i] = max(dp[i], dp[j] + 1);
            } 
        }
        ans = max(ans, dp[i]);
    }
    cout << ans;

    return 0;
}

如何优化呢?

题目要求,子序列中相邻两数相&不为0,即在整数的二进制表示中,只要有相同位置的二进制位为1,就可以满足要求。

也就是说,对于每个数,只要其二进制位上是1,则该数可以对以该位置为1的数结尾的子序列的长度产生1个贡献。

那么,可以针对每个数a[i],依次枚举每个二进制位,如果为1,则以该位置二进制为1的数结尾能产生的子序列长度就要加1,

对于同一个数a[i],在其以每个为1的二进制位置结尾所能产生的子序列最大长度应该更新为各个位置子序列长度的最大值。

设f[i]表示以第i位为1的数结尾能产生的最长子序列长度,

对于每一个数a[i],通过 a[i] & (1 << j),j =0~31,来判断每一位是否为1,如果第j位为1,则记录f[j] + 1的最大值maxx,这个maxx就是以a[i]结尾能产生的最长子序列长度。

再对于a[i],更新其每个为1的位上的f值,f[j] = maxx

重点说明:为什么要把a[i]二进制中每个为1位置的f值更新为maxx?

因为,能接在a[i]后面的数,只要满足与a[i]在任意相同二进制位为1即可,而a[i]能产生最大子序列长度是maxx,所有,a[i]的所有二进制为1的位置的f值都要更新为maxx。

记录最大的maxx即为答案。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;
int n;
int a[N];
int f[32]; //f[i]表示以第i位为1的数结尾产生的最长子序列长度,int一共32为,记录从0~31
int ans;

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];

    int maxx = 0;
    for(int i = 1;i <= n; i++)
    {
        for(int j = 0; j <= 31; j++)
        {
            if(a[i] & (1 << j)) //如果a[i]第j位是1
            {
                maxx = max(maxx, f[j] + 1); //第j位为1结尾的子序列长度都要加1,记录最大值,即以a[i]结尾
            }
        }
        for(int j = 0; j <= 31; j++)
        {
            if(a[i] & (1 << j))
            {
                f[j] = maxx; //把a[i]各个位置为1对应的f值更新为maxx,因为能接在a[i]后面的数只要在a[i]任意为1的位置一致即可
            }
        }
        ans = max(ans, maxx);
    }
    cout << ans;

    return 0;
}

 

标签:maxx,二进制位,int,洛谷题,好题,P4310,序列,长度,dp
From: https://www.cnblogs.com/jcwy/p/18182783

相关文章

  • 洛谷题单指南-动态规划2-P1833 樱花
    原题链接:https://www.luogu.com.cn/problem/P1833题意解读:在有限的时间内,看n株樱花树,第i株樱花树可以看pi次,看每株樱花树耗费时间ti,看每株樱花树一次美学值ci,求最多能看到多少美学值。解题思路:本题实质是一个混合背包问题(pi>0是多重背包,pi=0是完全背包):背包容量:总时间,可以根据......
  • 洛谷题单指南-动态规划2-P1854 花店橱窗布置
    原题链接:https://www.luogu.com.cn/problem/P1854题意解读:F束花依次放入V个花瓶,每个花瓶最多一朵,且花的顺序在花瓶中递增,计算最大的美学值,并且输出每朵花具体放置方案。解题思路:首先想到的的DFS法,对于每一朵花,枚举所有的摆放方案,累加美学值,并记录放置位置,完成一种方案就记录最......
  • 洛谷题单指南-动态规划2-P1435 [IOI2000] 回文字串
    原题链接:https://www.luogu.com.cn/problem/P1435解题思路:方法1:回文字串的特点是,正着读、反着读是一样的换一个思路,对于一个字符串s,正序、逆序公共的部分就是已经是回文的部分,剩余的部分就是要插入的字符所以,问题转换为,计算一个字符串正序、逆序的最长公共子串,然后剩下的长度......
  • 好题——图论
    前言本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。带!号的题是基础例题,带*号的是推荐首先完成的题(有一定启发性的)。图论最短路P1119灾后重建此题看到以后以为是很简单的最短路问题(实际也不难),就写了dijkstra,然后光荣的tie......
  • 好题——动态规划
    前言本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。带!号的题是基础例题,带*号的是推荐首先完成的题(有一定启发性的)。动态规划线性动态规划!JuryCompromise(蓝书例题)看到题目比较容易的想到:定义:f[i][j][k]为\(i\)表示考......
  • 好题——数学与数据结构
    前言本文章将会持续更新,主要是一些个人觉得比较妙的题,主观性比较强(给自己记录用的),有讲错请补充。带!号的题是基础例题,带*号的是推荐首先完成的题(有一定启发性的)。组合数P6620[省选联考2020A卷]组合数问题运用斯特林数好的例题,普通幂转下降幂。用到第二类斯特林数。\[......
  • 洛谷题单指南-动态规划2-P1091 [NOIP2004 提高组] 合唱队形
    原题链接:https://www.luogu.com.cn/problem/P1091题意解读:要挑选一个最长的先上升后下降的序列,求其余的元素数量解题思路:先计算正向的最长上升子序列,设f[i]表示以i结尾的正向最长上升子序列再计算逆向的最长上升子序列,设g[i]表示以i结尾的逆向最长上升子序列再枚举所有的i<j,m......
  • 洛谷题单指南-动态规划2-P1004 [NOIP2000 提高组] 方格取数
    原题链接:https://www.luogu.com.cn/problem/P1004题意解读:从起点走到终点,走两次,计算最大路径和,第一次走过的点数值变为0。解题思路:直观上思考,可以先从起点走到终点,计算最大路径和,并记录走过的所有点,然后把所有点的数值置为0,再从起点走到终点,计算最大路径和,把两次的最大路径......
  • 洛谷题单指南-动态规划2-P2679 [NOIP2015 提高组] 子串
    原题链接:https://www.luogu.com.cn/problem/P2679题意解读:在a中按顺序挑选k个子串,使得这些子串连在一起正好和b相等,求方案数。解题思路:这样的题目,无外乎两个思路:DFS暴搜(得部分分)、动态规划动态规划不好想,还是先暴搜吧!1、DFS暴搜搜索的思路就是:从a起始位置开始,一直找到跟b前......
  • 洛谷题单指南-动态规划2-P1439 【模板】最长公共子序列
    原题链接:https://www.luogu.com.cn/problem/P1439题意解读:求最长公共子序列的长度。解题思路:1、O(n^2)的方法:动态规划设两个排列为a,b设dp[i][j]表示a[1~i]与b[1~j]的最长公共子序列长度根据公共子序列结尾是否包含a[i]、b[j]是否相等分情况讨论:如果a[i]==b[j]  则结尾......