过河卒&采药&精卫填海&质数和分解

动态规划-过河卒

题目链接

#include<bits/stdc++.h>
using namespace std;
int n, m, x, y;
int a[30][30];
long long dp[25][25];
int main(){
    cin >> n >> m >> x >> y;
    //标记障碍的位置
    a[x][y] = 1, a[x + 1][y + 2] = 1, a[x + 2][y + 1] = 1;
    if (x - 2 >= 0 && y - 1 >= 0)  a[x - 2][y - 1] = 1;
    if (x - 2 >= 0)  a[x - 2][y + 1] = 1;
    if (x - 1 >= 0)  a[x - 1][y + 2] = 1;
    if (y - 1 >= 0)  a[x + 2][y - 1] = 1;
    if (y - 2 >= 0)  a[x + 1][y - 2] = 1;
    if (x - 1 >= 0 && y - 2 >= 0)  a[x - 1][y - 2] = 1;
    //初始化
    for (int i = 1; i <= n; i++){
        if (a[i][0] == 1){
            break;
        }
        dp[i][0] = 1;
    }
    for (int j = 1; j <= m; j++){
        if (a[0][j] == 1){
            break;
        }
        dp[0][j] = 1;
    }
    //递推
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            if (a[i][j] == 1){
                continue;
            }
            else {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
    }
    printf("%lld\n", dp[n][m]);
    return 0;
}
注意:注意数据范围,long long 输出的时候不要忘了用lld
long long dp[25][25];
printf("%lld\n", dp[n][m]);

动态规划-采药

题目链接

就是一个简单的0-1背包的变式,不多赘述

//动态规划-采药
#include<bits/stdc++.h>
using namespace std;
int T, n;
int dp[20000], useTime[110], value[110];
//dp[j]表示在j时间内能取到的最大价值
int main(){
    cin >> T >> n;
    for (int i = 0; i < n; i++){
        cin >> useTime[i] >> value[i];
    }
    for (int i = 0; i < n; i++){
        for (int j = T; j >= useTime[i]; j--){
            dp[j] = max(dp[j], dp[j - useTime[i]] + value[i]);
        }
    }
    printf("%d\n", dp[T]);

    return 0;
}

动态规划-装箱

题目链接

同上

//动态规划-装箱问题
#include<bits/stdc++.h>
using namespace std;
int n, V;
int dp[21000], weight[50];
//dp[j]表示箱子容量为j时,能取到的最大价值
int main(){
    cin >> V >> n;
    for (int i = 0; i < n; i++){
        cin >> weight[i];
    }
    for (int i = 0; i < n; i++){
        for (int j = V; j >= weight[i]; j--){
            dp[j] = max(dp[j], dp[j - weight[i]] + weight[i]);
        }
    }
    printf("%d\n", V - dp[V]);
    return 0;
}

动态规划-精卫填海

题目链接

//动态规划-精卫填海
#include<bits/stdc++.h>
using namespace std;
const int N = 10000;
int V, n, strengthSum;
int dp[N], strength[N], weight[N];
//dp[j]表示消耗体力j能搬运的最大容量
int main(){
    cin >> V >> n >> strengthSum;
    for (int i = 0; i < n; i++){
        cin >> weight[i] >> strength[i];
    }
    //初始化
    //递推
    for (int i = 0; i < n; i++){
        for (int j = strengthSum; j >= strength[i]; j--){
            dp[j] = max(dp[j], dp[j - strength[i]] + weight[i]);
        }
    }
    if (dp[strengthSum] < V){
        printf("Impossible\n");
    }
    else {
        for (int j = 1; j <= strengthSum; j++){
            if (dp[j] >= V){
                printf("%d\n", strengthSum - j);
                break;
            }
        }
    }
    return 0;
}

动态规划-质数和分解

题目链接

知识点:

  • 完全背包,

  • 求种类的动态规划,

  • 预处理

以后求种类的动态规划题一定要想到以下状态转移方程:

dp[j] += dp[j - nums[i]];
//动态规划DP基础篇-质数和分解
#include<bits/stdc++.h>
using namespace std;
int n, k;
int dp[200], prime[200];
//dp[j]表示整数j可以分解成的不同的质数和总数
bool judgePrime(int x){
    for (int i = 2; i <= sqrt(x); i++){
        if (x % i == 0){
            return 0;
        }
    }
    return 1;
}
int main(){
    for (int i = 2; i <= 200; i++){
        if (judgePrime(i) == 1){
            prime[++k] = i;
        }
    }
    dp[0] = 1;
    for (int i = 1; i <= k; i++){
        for (int j = prime[i]; j <= 200; j++){
            dp[j] += dp[j - prime[i]];
        }
    }
    while (~scanf("%d", &n)){
        printf("%d\n", dp[n]);
    }  
    return 0;
}

总结

对于动态规划的题目,首先要明确dp数组的含义,这是重中之重,不然想要AC是不可能的,能求max问题就不要求min问题,动态规划有两个难点:

  • dp数组含义是否明确

  • 状态转移方程是否正确

明确dp数组含义还是需要大量的经验的,还需要不断地刷dp题,至于状态转移方程的话,就需要自己画图举例总结了。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值