当前位置: 首页 > article >正文

算法-动态规划二

题目
Michael 喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 2424-1717-1616-11(从 2424 开始,在 11 结束)。当然 2525-2424-2323-\ldots…-33-22-11 更长。事实上,这是最长的一条。

输入格式
输入的第一行为表示区域的二维数组的行数 RR 和列数 CC。下面是 RR 行,每行有 CC 个数,代表高度(两个数字之间用 11 个空格间隔)。

输出格式
输出区域中最长滑坡的长度。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
using namespace std;
int a[100][100];
int n,m;
int Back_sum;
int dp[100][100];//记录每次的最大值
int way[4][2]= {0,1,1,0,0,-1,-1,0};
//定义一个二维数组a,用于存储输入的数字
//定义两个整数n和m,用于存储输入的行数和列数
//定义一个整数Back_sum,用于存储每次的最大值
//定义一个二维数组dp,用于记录每次的最大值
//定义一个二维数组way,用于存储四个方向的坐标
void dfs(int i,int j,int sum) {
    //定义一个递归函数dfs,用于深度优先搜索
    if(dp[i][j]!=1) {
        //如果dp[i][j]不等于1,说明已经访问过,直接返回
        Back_sum = max(Back_sum,sum-1+dp[i][j]);
        //更新Back_sum的值
        return;//
    }
    //如果dp[i][j]等于1,说明还没有访问过
    Back_sum = max(Back_sum,sum);
    //更新Back_sum的值
    for(int k = 0; k < 4; k++) {
        //遍历四个方向
        int x = i+way[k][0];
        int y = j+way[k][1];//!!!坐标的位置
        //计算新的坐标
        if(x>=0&&y>=0&&x<n&&y<m&&a[x][y]<a[i][j]) {
            //如果新的坐标在范围内,且新的数字小于当前的数字
            dfs(x,y,sum+1);//不接收Back_sum!!
            //递归调用dfs函数
        }
    }
}
int main() {
    //定义一个主函数
    cin>>n>>m;
    //输入行数和列数
    fill(dp[0],dp[0]+10000,1);
    //将dp数组初始化为1
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            cin>>a[i][j];
        }
    }
    //输入数字
    int ans=0;
    //定义一个整数ans,用于存储最终的结果
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            //遍历数组
            Back_sum = 0;
            //将Back_sum初始化为0
            dfs(i,j,1);
            //调用dfs函数
            dp[i][j] = Back_sum;//Back_sum传出来!!!
            //更新dp数组的值
            ans = max(ans,dp[i][j]);
            //更新ans的值
        }
    }
    printf("%d\n",ans);


    //输出最终的结果
}

5 5 
1 2 3 4 5 
16 17 18 19 6
15 24 25 20 7 
14 23 22 21 8
13 12 11 10 9
25

场景中包括多个长度和高度各不相同的平台。 地面是最低的平台,高度为零,长度无限。

Jimmy老鼠在时刻0从高于所有平台的某处开始下落, 它的下落速度始终为1米/秒。当Jimmy落到某个平台 时,游戏者选择让它向左还是向右跑,它跑动的速度 也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下 落。Jimmy每次下落的高度不能超过MAX米,不然就 会摔死,游戏也会结束。

设计一个程序,计算Jimmy到地面时可能的最早时间。

输入数据 第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是 四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面), X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接 下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示 平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。

所有坐标的单位都是米。 Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的 边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保Jimmy 一定能安全到达地面。

输出要求 对输入的每组测试数据,输出一个整数, Jimmy到地面时可能的最早时间。

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1005;
const int INF = 0x3f;
typedef struct Value{
    int l, r;   //l表示左端点,r表示平台右端点
    int h;      //h表示平台高度
}Value;
Value value[MAXN];

bool cmp(Value t1, Value t2) {      //按照平台高度从低到高排序
    return t1.h < t2.h;
}

int dp[MAXN][2];    //dp[i][0]表示从第i个平台左端落下时,到达地面最短时间,dp[i][1]表示从第i个平台右端落下时,到达地面最短时间
int main() {
int main() {
    int t;
    cin >> t;
    while(t--) {
        memset(dp, INF, sizeof(dp));
        int N, X, Y, MAXH;      //MAXH表示最大下落高度
        cin >> N >> X >> Y >> MAXH;
        for(int i = 1; i <= N; i++) {
            cin >> value[i].l >> value[i].r >> value[i].h;
        }
        sort(value+1, value+N+1, cmp);      //按照高度排序
        
        value[0].l = -20005, value[0].r = 20005;       //将地面当作0号平台,且长度无限长 
        value[0].h = 0; 
        value[N+1].l = value[N+1].r = X;            //将起点当作最后一个平台,其长度为0
        value[N+1].h = Y;
        
        dp[0][0] = dp[0][1] = 0;
        for(int i = 1; i <= N+1; i++) {
            //找寻从左端点落下,可以掉落到的平台位置
            int j = i - 1;
            while(j >= 0 && value[i].h - value[j].h <= MAXH) {
                if(value[i].l >= value[j].l && value[i].l <= value[j].r) {
                    break;
                }
                j--;
            }
            if(value[i].h - value[j].h <= MAXH) {       //保证不会摔死的情况下,寻找最优
                if(j) {     //非地面,所以可能需要走一段路
                    dp[i][0] = min(dp[j][0] + value[i].l - value[j].l, dp[j][1] + value[j].r - value[i].l) + value[i].h - value[j].h;
                }else {
                    dp[i][0] = value[i].h - value[j].h;
                }
            }
            
            //找寻从右端点落下,可以掉落到的平台位置
            j = i - 1;
            while(j >= 0 && value[i].h - value[j].h <= MAXH) {      
                if(value[i].r >= value[j].l && value[i].r <= value[j].r) {
                    break;
                }
                j--;
            }
            if(value[i].h - value[j].h <= MAXH) {       //保证不会摔死的情况下,寻找最优
                 if(j) {                                //下落到非地面的平台上,如果是地面,则无需从端点走向下落点
                     dp[i][1] = min(dp[j][0] + value[i].r - value[j].l, dp[j][1] + value[j].r - value[i].r) + value[i].h - value[j].h;
                }else {
                    dp[i][1] = value[i].h - value[j].h;
                }
            }
        }
        cout << min(dp[N+1][0], dp[N+1][1]) << endl;
    }
    return 0;
}

神奇的口袋

有一个神奇的口袋,总的容积是40,用这个口袋可以变出 一些物品,这些物品的总体积必须是40。 

 John现在有n(1≤n ≤ 20)个想要得到的物品,每个物品 的体积分别是a1,a2……an。John可以从这些物品中选择一 些,如果选出的物体的总体积是40,那么利用这个神奇的 口袋,John就可以得到这些物品。现在的问题是,John有 多少种不同的选择物品的方式。

输入

        输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的 数目。接下来的n行,每行有一个1到40之间的正整数,分别 给出a1,a2……an的值。

输出

        输出不同的选择物品的方式的数目。

#include <iostream>
using namespace std;
int a[30];  int N;
int Ways[50][50];//Ways[i][j]表示从前j种物品里凑出体积i的方法数
int main()
 {
     cin >> N;
     memset(Ways,0,sizeof(Ways));
     for( int i = 1;i <= N; ++ i ) {
         cin >> a[i]; Ways[0][i] = 1;
     }
     Ways[0][0] = 1;
     for( int w = 1 ; w <= 40; ++ w ) {
         for( int k = 1; k <= N; ++ k ) {
             Ways[w][k] = Ways[w][k-1];
             if( w-a[k] >= 0)
                 Ways[w][k] += Ways[w-a[k]][k-1];
         }
     }
     cout << Ways[40][N];
     return 0;

}

3
20
20
20
3

01背包Charm Bracelet

【题目描述】
经典0—1背包问题,有n个物品,编号为i的物品的重量为w[i],价值为c[i],现在要从这些物品中选一些物品装到一个容量为m的背包中,使得背包内物体在总重量不超过m的前提下价值尽量大。

【输入】
第1行:两个整数,n(物品数量,n≤3500)和m(背包容量,m≤12880)。

第2..n+1行::每行二个整数w[i],c[i],表示每个物品的重量和价值。

【输出】
仅一行,一个数,表示最大总价值。

#include <iostream>
using namespace std;
const int SIZM = 12880;
int n, m;
int dp[SIZM];
signed main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        int w_i, c_i;
        cin >> w_i >> c_i;
        for (int j = m; j >= w_i; j--)
        {
            dp[j] = max(dp[j], dp[j - w_i] + c_i);
        }
    }
    cout << dp[m];
    return 0;
}

4 6
1 4
2 6
3 12
2 7


http://www.kler.cn/a/601062.html

相关文章:

  • 软件性能效率测试工具有哪些?专业第三方软件检测机构推荐
  • PyTorch 深度学习实战(24):分层强化学习(HRL)
  • Sqoop-试题
  • 结合DrRacket学习《如何设计程序,第二版》
  • 基于Python的机器学习入门指南
  • Blender配置渲染设置并输出动画
  • 在转换不同格式时,保持正确的宽高比可以避免画面变形
  • Python FastApi(5):请求体、查询参数和字符串校验
  • k8s存储介绍(四)hostpath
  • 智能汽车图像及视频处理方案,支持视频实时拍摄特效能力
  • uv - pip 接口
  • 【多媒体交互】Unity+普通摄像头实现UI事件分析
  • VUE项目初始化
  • MATLAB 绘制空间分布图 方法总结
  • 【MySQL】mysql日志文件
  • 【QT】Qlcdnumber的使用
  • openai-agents-python中 agents_as_tools.py 示例
  • vue-如何将组件内容作为图片生成-html2canvas
  • Android ADB工具使用教程(从安装到使用)
  • 代理记账的第三个十年