c++DP复习——你真的掌握DP了吗

文章目录

  • Problem1:玉米田
    • Part1:题目分析
    • Part2:代码
  • Problem2:皇宫看守
    • Part1:题目分析
    • Part2:代码
  • Problem3:骑士
  • 结语

Problem1:玉米田

题目链接

Part1:题目分析

通过数据范围(状压DP的时间复杂度是 2 n 2^n 2n)和输入数据( 0 0 0 1 1 1)这道题这是一道状压DP的题目,我们可以设计出状态 d p [ i ] [ s ] = 第 i 行种植玉米的情况为 s 时的情况数量 dp[i][s] = 第i行种植玉米的情况为s时的情况数量 dp[i][s]=i行种植玉米的情况为s时的情况数量
那么如何判断合不合法呢?我们先举几个例子:(把第 i i i层的 s s s记作 s i si si)
i i i层的 s s s 10 10 10
i + 1 i + 1 i+1层的 s s s 11 11 11
合不合法呢?
我们把它们装成二进制看一下:
1010 1010 1010
1011 1011 1011
很明显是不合法的,通过分析,我们得出如下结论:
上下层的判断 s i si si & s i + 1 > 0 si+1 > 0 si+1>0 就是不合法;
左右的判断 s i si si & ( s i > > 1 ) > 0 (si>>1)>0 (si>>1)>0就是不合法。

Part2:代码

根据分析,我们可以得出如下代码:

#include 
#include 

using namespace std;

const int N = 14, M = 1 << N, mod = 1e8;

int n, m, k;
int g[N];
int f[N][M];
vector state;
vector head[M];

bool check(int state)
{
    return  !(state & state << 1);
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++ i)
        for (int j = 0; j < m; ++ j)
            cin >> k, g[i] |= !k << j;
    for (int st = 0; st < 1 << m; ++ st)
        if (check(st))
            state.push_back(st);    //预处理合法状态
    for (auto st: state)
        for (auto ne_st: state)
            if (!(st & ne_st))
                head[st].push_back(ne_st);  //预处理合法状态的合法转移
    f[0][0] = 1;
    for (int i = 1; i <= n + 1; ++ i)
        for (auto st: state)
            if (!(st & g[i]))
                for (auto pre_st: head[st])
                    f[i][st] = (f[i][st] + f[i - 1][pre_st]) % mod;
    cout << f[n + 1][0] << endl;
    return 0;
}

Problem2:皇宫看守

题目链接

Part1:题目分析

c++DP复习——你真的掌握DP了吗_第1张图片

Part2:代码

#include
using namespace std;
#define endl '\n'
#define int long long
#define PII pair
#define For(i, a, b) for(int i = a;i <= b;i++)
const int N = 1e4 + 1000;
int f[N][3];
int in[N];
int h[N], e[N], ne[N], idx;
int n;
void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u){
    f[u][0] = 0;
    f[u][1] = 0x3f3f3f3f3f3f3f3f;
    f[u][2] = w[u];
    for (int i = h[u]; ~i;i = ne[i]){
        int j = e[i];
        dfs(j);
        f[u][0] += min({f[j][0], f[j][1], f[j][2]});
    }
    for (int i = h[u]; ~i;i = ne[i]){
        int j = e[i];
        f[u][1] = min(f[u][1], f[j][2] + f[u][0] - min(f[j][1], f[j][2]));
    }
}
signed main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    memset(h, -1, sizeof h);
    cin >> n;
    For (i, 1, n){
        int x, m;
        cin >> x >> w[x] >> m;
        while (m--){
            int y;
            cin >> y;
            add(x, y);
            in[y]++;
        }
    }
    int root = 1;
    while (in[root])
        root++;
    dfs(root);
    cout << min(f[root][1], f[root][2]);
    return 0;
}

Problem3:骑士

题目链接

这道题就作为课后练习啦,大家自行思考。

结语

今天的文章就到这里啦,三连必回哦。

你可能感兴趣的:(c++,c++,开发语言)