状态机模型

状态机

初次听到这个名字以为是多么高大上的难的东西,其实就是把一个物品或者一个活动分成不同的状态,这几个状态可以相互转换。

模型一:挑数字

有一串数字,你要从中挑几个数字,让其总和最大,但是不能连续挑数字。比如 1 2 3 4 5,如果挑了1,那么不能挑2,可以挑3或者是4。且数列是无序的。

1.首先思考可以分成什么样的状态。
2.然后发现状态可分为每个数字挑或者不挑。那么用一个二维数组来表示状态,f[i][0]和f[i][1],0代表不挑选,1代表挑选。
3.那么这两种状态是如何转化的呢?首先思考一个问题,如果我选了前一个那么目前的这一个我一定不能选,如果前一个不选,那么我可以选目前的这个。所以可以得出一个转移方式。
(1).f[i - 1][1]->f[i][0].
(2).f[i - 1][0]->f[i][0],f[i - 1][0]->f[i][1].

4.那么我们就可以列出转移方程了。
f[i][0] = max(f[i - 1][0], f[i - 1][1]);
f[i][1] = f[i - 1][0] + w[i];

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =  110;
const int INF = 0x3f3f3f3f;
int n;
int w[N], f[N][2];
int main()
{
    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;
}

模型二:股票状态机Ⅰ

关于股票模拟两个操作,可以买入和卖出,当你手中没有货时,可以买入,也可以不买入,当手中有货时,可以卖出和不卖出,最多可以进行m次交易,然后问n天后最多能赚多少钱?

1.首先这个问题有三个限制条件,第几天,有无货,交易多少次。
2.分析状态,有三个限制条件,那么我们用一个三维数组表示状态。将买入的时候算作多交易一次。
f[i][j][0]表示在前i天,发生了j次交易之后手中无货最大的总钱数,f[i][j][1]表示在前i天,发生了j次交易之后手中有货最大的总钱数。
3.推出转移方程:
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]);
w[i]代表第i天的股价是多少。
因为定义的是买入的时候算作一次交易,所以只有在自己手中无货的时候,并且要买入的时候才算做j - 1。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =  100010, M = 110;
const int INF = 0x3f3f3f3f;
int n, m;
int w[N], f[N][M][2];
int main()
{
    cin >> n >> m;
    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 <= m; 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 < m; i ++) res += max(res, f[n][i][0]);
    cout << res << endl;
}

模型三:股票状态机Ⅱ

关于股票模拟两个操作,可以买入和卖出,当你手中没有货时,可以买入,也可以不买入,当手中有货时,可以卖出和不卖出,卖出之后,会有一天的冻结期,限制在冻结期时候不能买入任何股票,问n天后最多能赚多少钱?
这个也和上面两个一样的分析方式。可以看代码推,也可以自己推着写出代码。😉😉😉


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =  100010;
const int INF = 0x3f3f3f3f;
int n;
int w[N], 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][2], f[i - 1][1]);
    }
    cout << max(f[n][1], f[n][2]) << endl;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页