AT3575 101 to 010(DP)

Posted lihan123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AT3575 101 to 010(DP)相关的知识,希望对你有一定的参考价值。

满分做法:

这道题蛮难想的,(dp[i])表示到i位置的最大操作数,(11111101)(1011111)这两种情况我们可求出它的最大操作数为长度(-2),并发现整个序列的操作数可以拆分成几个小序列的最大操作做次数之和。

所以我们要记录(l[i])表示左边离(i)最近的(0)的位置,并得出转移:

(dp[i]=max(dp[i],dp[l[i-2]]+i-l[i-2]-2)),(dp[i]=max(dp[i],dp[l[i-2]+1]+i-l[i-2]-1-2)) (s[i-1]==‘0‘&&s[i-2]==‘1‘)。为什么会是两个呢?

因为这个序列可能长这样:(111111011111101),这样对于第一个转移来说第二个明显更优,而对于(001111101)这样的序列,第一个更优.

(dp[i]=max(dp[i],dp[l[i]-2]+i-l[i]+2-2)) (l[i]>1&&s[l[i]-1]==‘1‘),剩下的直接赋值即可。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxm=500007;
char s[maxm];
int n;
int dp[maxm];//到i位置的最大操作数 
int l[maxm];//在左边离i最近的0的位置 
int main()
{
 scanf("%d",&n);
 scanf("%s",s+1);
 for(int i=1;i<=n;i++)
 {
  if(s[i]=='1') l[i]=l[i-1];
  else l[i]=i;  
 }
 for(int i=1;i<=n;i++)
 {
   dp[i]=dp[i-1];
   if(s[i]=='1')
   {
     if(s[i-1]=='0'&&s[i-2]=='1')
     {
       dp[i]=max(dp[i],dp[l[i-2]]+i-l[i-2]-2);//100|11111101的贡献为他们的长度-2,
       dp[i]=max(dp[i],dp[l[i-2]+1]+i-l[i-2]-1-2);//11111101|11111101
     }
     else if(l[i]>1&&s[l[i]-1]=='1')
     {
      dp[i]=max(dp[i],dp[l[i]-2]+i-l[i]+2-2);//101111111
     }
   }
 }
 printf("%d
",dp[n]);
 return 0;  
}

以上是关于AT3575 101 to 010(DP)的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 每日一题 89. 格雷编码

Atcoder ARC101 E 树dp

WARNING: at drivers/gpio/gpiolib.c:101 gpio_ensure_requested+0x5c/0x118()

89. 格雷编码

AT2567 RGB Sequence dp

[Recap] Ruby 101 at Fudan University