poj 1088 / 3624两道简单DP

2024-04-22 06:08
文章标签 简单 dp poj 两道 3624 1088

本文主要是介绍poj 1088 / 3624两道简单DP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

                                                                                        滑雪
Time Limit: 1000MS
Memory Limit: 65536K
Total Submissions: 90776
Accepted: 34215

Description

Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
 1  2  3  4 516 17 18 19 615 24 25 20 714 23 22 21 813 12 11 10 9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。

Input

输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。

Output

输出最长区域的长度。

Sample Input

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

Sample Output

25



题目意思很明白,求一条最长的路。这题很多方法做,dfs 可以,dp 也可以, 不过个人感觉还是dp效率比较高
这题卡了我一会,把二维数组变到一维的时候以为是index = (i - 1) * n + j 其实应该是 index = (i - 1) * m + j !!!!
这里的二维数组从1 1 开使到 n m结束
思路:
因为这个图的高度没啥顺序关系,你只能确定某一点能不能往周围走,不能确定某一点往哪边走能走的最远,所以得把所有点从小到大排序,然后从顺序小的点开始,刷新周围比他高的点的路径,所以需要dp数组记下坐标,高度(排序时用),最大长度。。。从小到大刷新,则最后高度高的点的路程一定是最长的。。
/** poj.cpp**  Created on: 2016年7月20日*      Author: triose*///#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define enter putchar(10)
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define repe(i,a,b) for(int i = (a); i <= (b); ++i)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfP(a) printf("%d %d\n",a.fi,a.se)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define PR(a,b) pair<a,b>
#define fi first
#define se second
#define LL long long
#define DB double
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
int n, m;
#define N 110
#define M 10010
int a[N][N];
struct Node {int x, y;int high;int len;friend bool operator < (const Node & a, const Node & b) {return a.high < b.high;}
};
Node dp[M];
int max_len;
void check() {repe(i, 1, n * m) {printf("%d%c", dp[i].len, (i % m == 0 ? '\n' : ' '));}
}
void flash(int pos) {int x = dp[pos].x;int y = dp[pos].y;int flag1 = (x - 1) * m + y;rep(i, -1, 2) {rep(j, -1, 2) {int tmpx = x + i; int tmpy = y + j;if(i == j || i == -j) continue;if(tmpx > n || tmpx < 1 || tmpy < 1 || tmpy > m) continue;int flag2 = (tmpx - 1) * m + tmpy;if(a[tmpx][tmpy] > a[x][y]) {dp[flag2].len = Max(dp[flag2].len, dp[flag1].len + 1);max_len = Max(dp[flag2].len, max_len);}}}
}
int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);
//	freopen("Out.txt", "w", stdout);
#endifwhile(~sfd(n, m)) {max_len = 1;repe(i, 1, n) {repe(j, 1, m) {sf(a[i][j]);int tmp = (i - 1) * m + j;dp[tmp].x = i; dp[tmp].y = j;dp[tmp].high = a[i][j];dp[tmp].len = 1;}}int cnt = n * m;sort(dp + 1, dp + cnt + 1);repe(i, 1, cnt) flash(i);pf(max_len);
//		check();}return 0;
}




Charm Bracelet
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 33137 Accepted: 14690

Description

Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).

Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di

Output

* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

Sample Input

4 6
1 4
2 6
3 12
2 7

Sample Output

23

题目描述都没看,看到数据就知道是个裸的01背包。。秒秒钟敲出来发现既然TLE(百练上超时,POJ  MLE)!!!十分不解。。
先贴超内存代码:
/** poj.cpp**  Created on: 2016年7月20日*      Author: triose*///#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define enter putchar(10)
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define repe(i,a,b) for(int i = (a); i <= (b); ++i)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfP(a) printf("%d %d\n",a.fi,a.se)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define PR(a,b) pair<a,b>
#define fi first
#define se second
#define LL long long
#define DB double
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
int n, m;
#define N 3500
#define M 13000
int dp[N][M];
int v[N], w[N];
int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);
//	freopen("Out.txt", "w", stdout);
#endifwhile(~sfd(n, m)) {repe(i, 1, n) sfd(w[i], v[i]);mem(dp, 0);repe(i, 1, n) {for(int j = 1; j <= m; j++) {if(j >= w[i])dp[i][j] = Max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);else dp[i][j] = dp[i - 1][j];}}pf(dp[n][m]);}return 0;
}


01背包原理就不说了,都被讲烂了
接下来看怎么优化。
核心的代码在这:
if(j >= w[i])dp[i][j] = Max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
else dp[i][j] = dp[i - 1][j];
可见:dp[i][j]的值在dp数组上只与dp[i][k] (k <= j)的值有关系。如果上一行某个状态dp[i - 1][k]满足条件,则等于这个状态加第i个物品的价值。如果不满足条件,则就等于上一行的当前状态dp[i - 1][j]。
那么第 [i, i - 2]区间里的值对确定当前状态是无用的,那为什么要保存他们?
所以采用滚动数组的方式:
repe(i, 1, n) {for(int j = m; j >= w[i]; j--) {dp[j] = Max(dp[j - w[i]] + v[i], dp[j]);}
}
为什么能这样?因为和上面那段代码等效。j的循环会选择性执行这一句,dp[j] = Max(dp[j], dp[j - w[i]] + v[i])
而没被选择到的(j < w[i])的dp[j] 还是等于自身。从而通过这种方法降低了数组的维度。节省了时间和空间。

/** poj.cpp**  Created on: 2016年7月20日*      Author: triose*///#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define enter putchar(10)
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define repe(i,a,b) for(int i = (a); i <= (b); ++i)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfP(a) printf("%d %d\n",a.fi,a.se)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define PR(a,b) pair<a,b>
#define fi first
#define se second
#define LL long long
#define DB double
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
int n, m;
#define N 3500
#define M 13000
int v[N], w[N];
int dp[M];
int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);
//	freopen("Out.txt", "w", stdout);
#endifwhile(~sfd(n, m)) {repe(i, 1, n) sfd(w[i], v[i]);mem(dp, 0);repe(i, 1, n) {for(int j = m; j >= w[i]; j--) {dp[j] = Max(dp[j - w[i]] + v[i], dp[j]);}}pf(dp[m]);}return 0;
}


这篇关于poj 1088 / 3624两道简单DP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924973

相关文章

一份LLM资源清单围观技术大佬的日常;手把手教你在美国搭建「百万卡」AI数据中心;为啥大模型做不好简单的数学计算? | ShowMeAI日报

👀日报&周刊合集 | 🎡ShowMeAI官网 | 🧡 点赞关注评论拜托啦! 1. 为啥大模型做不好简单的数学计算?从大模型高考数学成绩不及格说起 司南评测体系 OpenCompass 选取 7 个大模型 (6 个开源模型+ GPT-4o),组织参与了 2024 年高考「新课标I卷」的语文、数学、英语考试,然后由经验丰富的判卷老师评判得分。 结果如上图所

回调的简单理解

之前一直不太明白回调的用法,现在简单的理解下 就按这张slidingmenu来说,主界面为Activity界面,而旁边的菜单为fragment界面。1.现在通过主界面的slidingmenu按钮来点开旁边的菜单功能并且选中”区县“选项(到这里就可以理解为A类调用B类里面的c方法)。2.通过触发“区县”的选项使得主界面跳转到“区县”相关的新闻列表界面中(到这里就可以理解为B类调用A类中的d方法

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python

宝塔面板部署青龙面板教程【简单易上手】

首先,你得有一台部署了宝塔面板的服务器(自己用本地电脑也可以)。 宝塔面板部署自行百度一下,很简单,这里就不走流程了,官网版本就可以,无需开心版。 首先,打开宝塔面板的软件商店,找到下图这个软件(Docker管理器)安装,青龙面板还是安装在docker里,这里依赖宝塔面板安装和管理docker。 安装完成后,进入SSH终端管理,输入代码安装青龙面板。ssh可以直接宝塔里操作,也可以安装ssh连接

XMG Quartz2D的简单使用

// //  Quratz2DView.m //  Quartz2D // //  Created by 王宁 on 16/5/6. //  Copyright © 2016年 ylshmacmini. All rights reserved. // #import "Quratz2DView.h" //Quartz@2D是一个二维绘图引擎,同时支

网页脚本输入这么简单

如何在网页中进行脚本操作呢? 研究了一下,很简单,用google浏览器的Console直接操作javaScript。思路: Created with Raphaël 2.1.0 开始 输入(如何输入) 点击(如何点击) 结束 下面是,通过脚本刷直播屏的实现,直接在Console输入即可 var words=new Arra

Linux网络编程之简单并发服务器

1.概念 与前面介绍的循环服务器不同,并发服务器对服务请求并发处理。而循环服务器只能够一个一个的处理客户端的请求,显然效率很低. 并发服务器通过建立多个子进程来实现对请求的并发处理,但是由于不清楚请求客户端的数目,因此很难确定子进程的数目。因此可以动态增加子进程与事先分配的子进程相结合的方法来实现并发服务器。 2. 算法流程 (1)TCP简单并发服务器:     服务器子进程1:

上海邀请赛 A题目 HDU 5236(dp)

先求出没有ctrl+s的时候构造长度为i的期望f[i] 。然后枚举保存的次数,求出最小即可。 #include<cstdio>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<string>#include<cstring>#include<iostream>#include<map>

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符。然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string