牛妹愛數列(動態規劃 dp)

2021-10-23 14:22:57 字數 2881 閱讀 4145

題目描述:

牛妹正在玩乙個數列

他手裡有乙個長度為n的序列a,保證它是乙個01序列,並執行以下兩種操作:

1.單點修改:將位置x上的數翻轉(0變1,1變0);

2.字首修改:將位置1~x上的數翻轉(每個數都0變1,1變0)。

他現在想要最小化翻轉次數,使得數列上的所有數都變為0。

輸入描述:

第一行,輸入乙個數n。

第二行,輸入n個數,第i個數表示ai。

輸出描述:

輸出最小翻轉次數。

示例1

輸入10

1 0 1 1 0 0 0 1 0 0

輸出

3

樣例解釋:

第一次使用(1)操作, 把2改掉: 1 1 1 1 0 0 0 1 0 0

第二次使用(2)操作, 把1-4全部改掉: 0 0 0 0 0 0 0 1 0 0

第三次使用(1)操作, 把8改掉: 0 0 0 0 0 0 0 0 0 0

備註:

資料保證1<= n <=10^5,0<= ai <=1。

題意:就是求把所有的數翻轉成0的最小翻轉數。

思路:就是dp關鍵是寫出狀態轉移方程即可。

dp[i][0]表示[1,i]全部翻轉成0所需的最小翻轉次數

dp[i][1]表示[1,i]全部翻轉成0所需的最小翻轉次數

定義陣列a存n個數

如果a[i] == 1 ,狀態轉移方程:

a[i

]==1

dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1); \\ \\ dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]); \end

a[i]==

1⎩⎪⎨

⎪⎧​d

p[i]

[0]=

min(

dp[i

−1][

0]+1

,dp[

i−1]

[1]+

1);d

p[i]

[1]=

min(

dp[i

−1][

0]+1

,dp[

i−1]

[1])

;​

dp[i][0] = min ( [1,i-1] 區間變成0的最小次數在加上把a[i]這個1翻成0的這一步 , 把[1,i-1] 區間翻成1的最小次數(此時[1,i]區間全是1)然後把[1,i]這個區間翻轉,次數加1 )

dp[i][1] = min ( [1,i-1]翻成0的最小次數,然後我再多一步把[1,i-1]區間翻一下,因為a[i]為1,所以此時[1,i]就都是1了 , 因為a[i]就是1,所以,次數就與[1,i-1]翻成1的次數相等 )

其實a[i]==0 的狀態轉移方程可以由上面思想一樣,為了更好理解,我在此就再細說一遍

如果a[i] == 0 ,狀態轉移方程:

a[i

]==0

dp[i][0]=min(dp[i-1][0],dp[i-1][1]+1); \\ \\ dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1]+1); \end

a[i]==

0⎩⎪⎨

⎪⎧​d

p[i]

[0]=

min(

dp[i

−1][

0],d

p[i−

1][1

]+1)

;dp[

i][1

]=mi

n(dp

[i−1

][0]

+1,d

p[i−

1][1

]+1)

;​

dp[i][0] = min ( 因為a[i]=0,所以與區間[1,i-1]翻成0的次數相等 , 把區間[1,i-1]翻成1的次數多一步,把區間[1,i-1]整體翻一下,這時[1,i]就都是0了 )

dp[i][1] = min ( 區間[1,i-1]翻成0的次數,此時[1,i]就都是0,然後再把區間[1,i]翻一下,就全變成1了 , 區間[1,i-1]翻成1的步數,再加上把a[i]這個0翻成1的這一步 )

最後輸出區間[0,n]全變成0的最下次數,也就是dp[n,0]即可。

**:

#include

using

namespace std;

const

int maxn=

1e5+5;

int dp[maxn][2

],a[maxn]

;int

main()

for(

int i=

1;i<=n;i++

)else

// a[i] == 0

} cout<]<}return0;

}

加油!

共同努力!

keafmd

線性dp 牛妹愛數列

題目大意 有乙個長度為n的序列a,保證它是乙個01序列,並執行以下兩種操作 1.單點修改 將位置x上的數翻轉 0變1,1變0 2.字首修改 將位置1 x上的數翻轉 每個數都0變1,1變0 他現在想要最小化翻轉次數,使得數列上的所有數都變為0。資料保證 1 le n le 10 5,0 le a i ...

NowCoder 練習 牛妹愛數列(DP)

牛妹愛數列 他手裡有乙個長度為n的序列a,保證它是乙個01序列,並執行以下兩種操作 他現在想要最小化翻轉次數,使得數列上的所有數都變為0。輸出最小翻轉次數 示例1 輸出 min dp n 0 dp n 1 1 include using namespace std pragma gcc optimi...

牛客 牛妹愛數列 K K K

思路 剛開始考慮的是貪心,讓sum 0 遇到1就 0則 找到sum最大的時候,在這個時候反轉一次,這樣是會漏情況的 如 0 0 0 0 0 1 1 1 可以把0變為1 再全部變為0 那麼只能考慮dp了 首先要確定dp的意義,根據要求的 肯定是要dp n 為前n為都為0的 那麼考慮把dp i 定為 前...