【dp入门题】【跟着14练dp吧...囧】
A HDU_2048 数塔
dp入门题——数塔问题;求路径的最大和;
状态方程:
dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+a[i][j];
dp[n][j] = a[n][j];
其中dp[i][j]: 深度为i的第j个结点的最大和;
/*
Problem: HDU-2048
Tips: Easy DP
dp[i][j]: 深度为i的第j个结点的最大和;
dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+a[i][j];
dp[n][j] = a[n][j];
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = ;
int a[maxn][maxn], dp[maxn][maxn];
int n;
void DP()
{
memset(dp, , sizeof(dp));
for(int j = ; j <= n; j++) dp[n][j] = a[n][j];
for(int i = n-; i >= ; i--)
{
for(int j = ; j <= i; j++)
{
dp[i][j]=max(dp[i+][j], dp[i+][j+])+a[i][j];
}
}
printf("%d\n", dp[][]);
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i = ; i <= n; i++)
for(int j = ; j <= i; j++)
scanf("%d", &a[i][j]);
DP();
} return ;
}
B HDU_1176 免费馅饼
数塔问题变形
状态方程:
dp[i][j] = max(dp[i+1][j-1], dp[i+1][j], dp[i+1][j+1])+a[i][j]; (注意要从后往前推)
dp[i][10] = max(dp[i+1][j-1], dp[i+1][j])+a[i][10];
dp[i][0] = max(dp[i+1][j], dp[i+1][j+1])+a[i][0];
其中dp[i][j]:第i时刻在位置j的接到的最多馅饼数;
/*
Problem: HDU-2048
Tips: Easy DP
dp[i][j]: 深度为i的第j个结点的最大和;
dp[i][j] = max(dp[i+1][j-1], dp[i+1][j], dp[i+1][j+1])+a[i][j];
dp[i][10] = max(dp[i+1][j-1], dp[i+1][j])+a[i][10];
dp[i][0] = max(dp[i+1][j], dp[i+1][j+1])+a[i][0];
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = ;
int dp[maxn][], a[maxn][];
int main()
{
int n;
while(scanf("%d", &n) && n)
{
memset(a, , sizeof(a));
int maxt = ;
int t, p;
for(int i = ; i < n; i++)
{
scanf("%d%d", &p, &t);
a[t][p]++;
maxt = max(maxt, t);
}
memset(dp, , sizeof(dp));
for(int j = ; j <= ; j++) dp[maxt][j] = a[maxt][j];
for(int i = maxt-; i >= ; i--)
{
for(int j = ; j <= ; j++)
{
dp[i][j] = max(dp[i+][j], max(dp[i+][j+], dp[i+][j-]))+a[i][j];
}
dp[i][] = max(dp[i+][], dp[i+][])+a[i][];
dp[i][] = max(dp[i+][], dp[i+][])+a[i][];
} printf("%d\n", dp[][]);
}
return ;
}
C HDU_1087 Super Jumping! Jumping! Jumping!
状态方程:
dp[j] = v[i]<v[j] ? dp[i]+v[j] : dp[j];
dp[0] = 0;
其中dp[j]: 到第j步时,棋子的最大和
感觉自己推的方程毫无技术含量
/*
Problem: HDU-2048
Tips: Easy DP
dp[j]: 到第j步时,棋子的最大和
dp[j] = v[i]<v[j] ? dp[i]+v[j] : dp[j];
dp[0] = 0;
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = ;
int dp[maxn], v[maxn];
int main()
{
int n;
while(~scanf("%d", &n) && n)
{
memset(dp, , sizeof(dp));
int _max = ;
for(int i = ; i <= n; i++) {scanf("%d", &v[i]); dp[i] = v[i]; _max = max(_max, v[i]);}
dp[n+] = v[n+] = _max+; dp[] = v[] = ;
for(int i = ; i <= n; i++)
{
for(int j = i+; j <= n+; j++)
{
if(v[j] > v[i])
{
dp[j] = max(dp[j], dp[i]+v[j]);
}
}
}
printf("%d\n", dp[n+]-_max-);
}
return ;
}
E HDU_1058 Humble Numbers
求丑数。两种方法,之前一直用优先队列,dp的算法时间更短,这算法谁想出来的...
每个丑数都可以分解为2^a*3^b*5^c*7的乘积,每次找到最小的数分别乘以2,3,5,7然后放入队列中去。两种方法的基本原理都是这样。
dp:
/*
Problem: HDU 1058
Times: 62MS
Tips: Easy DP
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = ;
const int pri[] = {, , , };
LL dp[maxn];
LL Min(LL a, LL b, LL c, LL d)
{
return min(a, min(b, min(c, d)));
} void init()
{
int p1, p2, p3, p4;
p1 = p2 = p3 = p4 = ;
dp[] = ;
int a, b, c, d;
for(int i = ; i <= ; i++)
{
a = dp[p1]*;
b = dp[p2]*;
c = dp[p3]*;
d = dp[p4]*;
dp[i] = Min(a, b, c, d);
if(dp[i] == a) p1++;
if(dp[i] == b) p2++;
if(dp[i] == c) p3++;
if(dp[i] == d) p4++;
}
} int main()
{
init();
int n;
while(~scanf("%d", &n) && n)
{
if(n% == && n% != )
{
printf("The %dst humble number is %I64d.\n", n, dp[n]);
}
else if(n% == && n% != )
{
printf("The %dnd humble number is %I64d.\n", n, dp[n]);
}
else if(n% == && n% != )
{
printf("The %drd humble number is %I64d.\n", n, dp[n]);
}
else
printf("The %dth humble number is %I64d.\n", n, dp[n]);
} return ;
}
优先队列:
/*
Problem: HDU 1058
Times: 109MS
Tips: Easy DP
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<set>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
//typedef long long LL;
const int pri[] = {, , , };
LL ans[]; void init()
{
priority_queue<LL, vector<LL>, greater<LL> > pq;
set<LL> s;
pq.push(); s.insert();
for(int i = ; ; i++)
{
LL x = pq.top(); pq.pop();
ans[i] = x;
if(i == ) return ;
for(int j = ; j < ; j++)
{
LL t = pri[j]*x;
if(!s.count(t))
{
s.insert(t);
pq.push(t);
}
}
}
} int main()
{
init();
int n;
while(~scanf("%d", &n) && n)
{
if(n% == && n% != )
{
printf("The %dst humble number is %I64d.\n", n, ans[n]);
}
else if(n% == && n% != )
{
printf("The %dnd humble number is %I64d.\n", n, ans[n]);
}
else if(n% == && n% != )
{
printf("The %drd humble number is %I64d.\n", n, ans[n]);
}
else
printf("The %dth humble number is %I64d.\n", n, ans[n]); }
return ;
}
G HDU_1159 Common Subsequence
LIC入门题+滚动数组
状态方程:
dp[i][j] = (s[i]==s2[j]) ? dp[i-1][j-1]+1 : max(dp[i-1][j], dp[i][j-1]);
其中dp[i][j] :s1串到i处,s2串到j处时最长上升子串的长度;
由状态方程可以看出,只需要知道i-1时的状态就可以推出i时的状态,因此可以只用一个2*maxn的数组存储状态值,那么看方程也可以根据j-1的状态推出j时的状态啊为什么不用2*2的?虽然方程表面上看来是这样,但是别忘了j是随着i的递增而循环的,每次i改变,状态量都会更新;
/*
Problem: HDU 1159
Tips: LCS
*/ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<set>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = ;
char s1[maxn], s2[maxn];
int dp[][maxn];
void LCS()
{
int l1 = strlen(s1+), l2 = strlen(s2+);
memset(dp, , sizeof(dp));
for(int i = ; i <= l1; i++)
{
for(int j = ; j <= l2; j++)
{
if(s1[i] == s2[j])
dp[i%][j] = dp[(i-)%][(j-)]+;
else
dp[i%][j] = max(dp[(i-)%][j], dp[i%][(j-)]);
}
}
printf("%d\n", dp[l1%][l2]);
} int main()
{
while(~scanf("%s%s", s1+, s2+))
{
LCS();
}
return ;
}
H HDU_1003 Max Sum
最大连续子串和入门题;blog有原题题解,不再赘述。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<set>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = ;
int n;
int a[maxn];
int dp[maxn]; void DP()
{
memset(dp, , sizeof(dp));
int _max = -INF;
int s, e; s = e = ;
for(int i = ; i <= n; i++)
{
dp[i] = dp[i-]> ? dp[i-]+a[i] : a[i];
if(dp[i] > _max)
{
_max = dp[i]; e = i;
}
}
printf("%d ", _max);
s = e;
for(int i = e; i >= ; i--)
{
if(dp[i]<) break;
s = i;
}
printf("%d %d\n", s, e);
} int main()
{
int T; scanf("%d", &T);
for(int kase = ; kase < T; kase++)
{
if(kase) printf("\n");
printf("Case %d:\n", kase+);
scanf("%d", &n);
for(int i = ; i <= n; i++) scanf("%d", &a[i]);
DP();
}
return ;
}
I HDU_4540 威威猫系列故事——打地鼠
状态方程:
dp[i][j] = min(dp[i-1][pos_last]+abs(pos_last-pos_now));
dp[0][j] = dp[1][j] = 0;
其中dp[i][j]: 第i时刻打位于j位置的地鼠消耗能量的最小值。
/**/ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = ;
const int maxp = ;
int n, k;
int a[maxn][maxn];
int dp[maxn][maxp];
void DP()
{
memset(dp, INF, sizeof(dp));
for(int p = ; p < maxp; p++) dp[][p] = ;
for(int t = ; t <= n; t++)
for(int j = ; j < k; j++)
{
int pos_now = a[t][j];
int _min = INF;
for(int p = ; p < k; p++)
{
int pos_last = a[t-][p];
_min = min(_min, dp[t-][pos_last]+abs(pos_last-pos_now));
}
dp[t][pos_now] = _min;
}
int _min = dp[n][];
for(int p = ; p < k; p++)
_min = min(_min, dp[n][a[n][p]]);
printf("%d\n", _min);
} int main()
{
while(~scanf("%d%d", &n, &k))
{
for(int t = ; t <= n; t++)
for(int p = ; p < k; p++)
scanf("%d", &a[t][p]);
DP();
}
return ;
}
【dp入门题】【跟着14练dp吧...囧】的更多相关文章
- poj 3254 状压dp入门题
1.poj 3254 Corn Fields 状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...
- POJ 2342 树形DP入门题
有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...
- (树形DP入门题)Anniversary party(没有上司的舞会) HDU - 1520
题意: 有个公司要举行一场晚会.为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司等都可以邀请. ...
- UVA 674 Coin Change 换硬币 经典dp入门题
题意:有1,5,10,25,50五种硬币,给出一个数字,问又几种凑钱的方式能凑出这个数. 经典的dp题...可以递推也可以记忆化搜索... 我个人比较喜欢记忆化搜索,递推不是很熟练. 记忆化搜索:很白 ...
- 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题
[HDU 3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...
- HDU 2089 不要62【数位DP入门题】
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- poj 2955 区间dp入门题
第一道自己做出来的区间dp题,兴奋ing,虽然说这题并不难. 从后向前考虑: 状态转移方程:dp[i][j]=dp[i+1][j](i<=j<len); dp[i][j]=Max(dp[i ...
- 数位DP入门题——[hdu2089]不要62
数位DP是我的噩梦. 现在初三了,却没AC过数位DP的题目. 感觉数位DP都是毒瘤-- 题目 hdu不用登录也可以进去,所以就不把题目copy到这里来了. 题目大意 求区间[n,m][n,m][n,m ...
- 洛谷 P1879 玉米田(状压DP入门题)
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 相关变量解释: int M,N; int plant[maxn][maxn];/ ...
随机推荐
- MYSQL数据库性能调优之一:调优技术基础
1.mysql数据库优化技术有哪些? 2.数据库三层结构? 3.数据库3NF
- boost::bind 和 boost::function 基本用法
这是一篇介绍bind和function用法的文章,起因是近来读陈硕的文章,提到用bind和function替代继承,于是就熟悉了下bind和function的用法,都是一些网上都有的知识,记录一下,期 ...
- Shell字符串使用十进制转换
其实不知道该起什么题目. 先说下需求,线上的log是按照五分钟为粒度切分的,即每五分钟产生一个文件,19:04的log写入到 1900结尾的log文件中,19:05写入到1905结尾的log文件中. ...
- Android实例-全屏显示程序(XE10+小米2)(无图)
方法一:选中窗体->BorderStyle改为“None” 方法二: 1.下载第三方控件QAndroid.Shell 2.执行FShell.Execute('su -c mount -o rem ...
- 解决iPhone上select时常失去焦点,随意跳到下一个输入框,影响用户操作
window.addEventListener('load', function() { FastClick.attach(document.body); }, false); //300s延迟,解决 ...
- MVC神韵---你想在哪解脱!(十五)
在模型中添加验证规则 本节介绍如何在我们的Movie(电影)模型中添加一些验证规则,同时确认当用户使用我们的应用程序创建或编辑电影信息时将使用这些验证规则对用户输入的信息进行检查.首先,让我们在Mov ...
- SQl函数的写法
USE [ChangHong_612]GO/****** Object: UserDefinedFunction [dbo].[FN_GetProdQty] Script Date: 10/08/20 ...
- ADO.NET 快速入门(十一):连接池
这个示例演示了如何构建一个到数据源的连接池.你可以通过连接池部署高性能的应用程序.本例中使用连接串创建连接池,并且由 SqlConnection 自动管理. string connString; ...
- some scrum screenshots
backlog tracking progress Initial Stage Next Stage End
- Codeforces Beta Round #51 D. Beautiful numbers 数位dp
D. Beautiful numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55/p ...