【AcWing】【DP--State Machine Model】

state machine model

Thief Alfred

Ah Fu is an experienced thief. Taking advantage of the dark moon and high wind, Ah Fu planned to loot the shops on a street tonight.

There are a total of N stores on this street, and each store has some cash.

Ah Fu's prior investigation learned that only when he ransacked two adjacent shops at the same time , the alarm system on the street would be activated, and then the police would swarm.

As a thief who has always committed crimes cautiously, Ah Fu is unwilling to take the risk of being chased by the police to steal.

He wondered, the most he could get in cash tonight without calling the police?

input format

The first line of input is an integer T, indicating that there are T sets of data in total.

For each next set of data, the first line is an integer N, indicating that there are N stores in total.

The second line is N positive integers separated by spaces, indicating the amount of cash in each store.

The amount of cash in each shop does not exceed 1000.

output format

For each set of data, output one line.

This line contains an integer representing the amount of cash that Ah Fu can get without calling the police.

data range

1 ≤ T ≤ 50,
1 ≤ N ≤ 105

Input sample:

2
3
1 8 2
4
10 7 6 14

Sample output:

8
24

sample explanation

For the first group of samples, Ah Fu chooses the second shoplifting, and the amount of cash obtained is 8.

For the second group of samples, Ah Fu chooses the 1st and 4th shoplifting, and the amount of cash obtained is 10+14=24.

Problem-solving ideas:

Status means:

状态机:0  1
0 表示未选 1 表示选.
f[i][0], f[i][1] 表示所有走了i步,且当前位于状态j的所有走法。

insert image description here

State calculation:

Collection division:

最后一步的走法:最后一个不选 | 最后一个选
f[i][0]的划分方式:
从 0->0  f[i - 1][0]  // 前一个不选过来
从 1->0  f[i - 1][1]  // 前一个选了过来
f[i][1]的划分方式:
f[i - 1][0] + w[i]   // 只能前一个不选过来

The state transition equation is:

f[i][0] = max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + w[i];
res = max(f[n][0], f[n][1])
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10, INF = 0X3f3f3f3f;
int n;
int w[N], f[N][2];

int main()
{
    
    
    int T;
    cin >> T;
    while (T --)
    {
    
    
        int n; cin >> n;
        for (int i = 1; i <= n; i ++) cin >> w[i];
        f[0][0] = 0, f[0][1] = -INF; // 初始化入口
        // 状态更新
        for (int i = 1; i <= n; i ++)
        {
    
    
            f[i][0] = max(f[i - 1][0], f[i - 1][1]);
            f[i][1] = f[i - 1][0] + w[i];
        }
        cout << max(f[n][0], f[n][1]) << endl;
    }
    return 0;
}

Stock Trading IV

Given an array of length N, the ith number in the array represents the price of a given stock on day i.

Design an algorithm to calculate the maximum profit you can get, you can complete at most k transactions.

Note: You cannot participate in multiple transactions at the same time (you must sell the previous stock before buying again). A buy and sell is combined into one transaction.

input format

The first line contains integers N and k, indicating the length of the array and the maximum number of transactions you can complete.

The second line contains N positive integers not exceeding 10000, representing a complete array.

output format

Output an integer representing the maximum profit.

data range

1 ≤ N ≤ 105,
1 ≤ k ≤ 100

Input sample 1:

3 2
2 4 1

Output sample 1:

2

Input sample 2:

6 2
3 2 6 5 0 3

Output sample 2:

7

sample explanation

Example 1: Buy on day 1 (stock price = 2) and sell on day 2 (stock price = 4), this transaction can make profit = 4-2 = 2.

Example 2: Buy on day 2 (stock price = 2) and sell on day 3 (stock price = 6), this transaction can make profit = 6-2 = 4. Then, buy on the 5th day (stock price = 0) and sell on the 6th day (stock price = 3), this transaction can make profit = 3-0 = 3. Total profit 4+3 = 7.

Problem-solving ideas:

Status means:

状态机:0:手中无货	1:手中有货  
f[i][j][0]  表示所有只考虑前i天且正在进行第j次交易,并且手中无货的所有买法的集合
f[i][j][1]  表示所有只考虑前i天且正在进行第j次交易,并且手中有货的所有买法的集合

State calculation:

Collection division:

f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + w[i])
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i])
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10, M = 110, INF = 0x3f3f3f3f;
int n, k;
int w[N];
int f[N][M][2];
int main()
{
    
    
    cin >> n >> k;
    for (int i = 1; i <= n; i ++) cin >> w[i];
    // 初始化
    memset(f, -0x3f, sizeof f);
    for (int i = 0; i <= n; i ++) f[i][0][0] = 0;
    
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= k; j ++)
        {
    
    
            f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j][1] + w[i]);
			f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - w[i]);
        }
    int res = 0;
    for (int i = 0; i <= k; i ++) res = max(res, f[n][i][0]);
	cout << res << endl;
    return 0;
}

stock trading V

Given an array of length N, the ith number in the array represents the price of a given stock on day i.

Design an algorithm to calculate the maximum profit. You can complete as many transactions as possible (buy and sell a stock multiple times) subject to the following constraints:

  • You cannot participate in multiple transactions at the same time (you must sell the previous stock before buying it again).
  • After selling the stock, you cannot buy the stock the next day (that is, the freezing period is 1 day).

input format

The first line contains the integer N, representing the length of the array.

The second line contains N positive integers not exceeding 10000, representing a complete array.

output format

Output an integer representing the maximum profit.

data range

1 ≤ N ≤ 105

Input sample:

5
1 2 3 0 2

Sample output:

3

sample explanation

The corresponding transaction status is: [buy, sell, freeze period, buy, sell], the first transaction can get a profit of 2-1 = 1, the second transaction can get a profit of 2-0 = 2, and the total profit of 1+2 = 3.

f[i][0] = max(f[i - 1][0], f[i - 1][2] - w[i])
f[i][1] = f[i - 1][0] + w[i]
f[i][2] = max(f[i - 1][1], f[i - 1][2])
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10, INF = 0x3f3f3f3f;
int n;
int w[N];
int f[N][3];

int main()
{
    
    
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> w[i];
    
    f[0][0] = f[0][1] = -INF;
    f[0][2] = 0;
    
    for (int i = 1; i <= n; i ++)
    {
    
    
        f[i][0] = max(f[i - 1][0], f[i - 1][2] - w[i]);
        f[i][1] = f[i - 1][0] + w[i];
        f[i][2] = max(f[i - 1][1], f[i - 1][2]);
    }
    cout << max(f[n][1], f[n][2]) << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/laaa123mmm/article/details/128887291