递推求解专题训练
来源:互联网 发布:labview编程详解书 编辑:程序博客网 时间:2024/05/26 07:30
想要dp入门,感觉自己需要先写几题递推…..
hdu2044 2045 2046 2047 2048 2049 2050
//真正意义上第一题递推
hdu2044
传送门
题目:
有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。
其中,蜂房的结构如下所示。
Input
输入数据的第一行是一个整数N,表示测试实例的个数,然后是N 行数据,每行包含两个整数a和b(a < b < 50)
Output
对于每个测试实例,请输出蜜蜂从蜂房a爬到蜂房b的可能路线数,每个实例的输出占一行。
Sample Input
2
1 2
3 6
Sample Output
1
3
思路:假设i为起点,j为终点,那么会发现能直接到达j的点只有两个,j-1和j-2,那么i到j的总数量
d[i][j] = d[i][j-1] + d[i][j-2]; (i < j-2)
d[i][j] = 2; (i==j-2)
d[i][j] = 1; (i==j-1)
那好的,现在递推式就出来了,代码也就出来了。注意数据会爆int,用long long才能存下。
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define inf 0x3f3f3f3f#define LL long longLL d[50][50];int a,b;int num = 0;LL dfs(int i,int j){ LL ans = -1; if(d[i][j] != -1) return d[i][j]; if( i+1 == j ) ans = 1; else if(i+2 == j) ans = 2; else ans = dfs(i,j-1) + dfs(i,j-2); return d[i][j] = ans;}int main(){ int t; for(int i = 0; i < 50; i ++) for(int j = 0; j < 50; j++) d[i][j] = -1; scanf("%d",&t); for(int i = 1; i <= 50; i++) for(int j = i+1; j <= 50; j++) dfs(i,j); while(t--) { num = 0; scanf("%d%d",&a,&b); cout<<d[a][b]<<endl; } return 0;}
//hdu2045
题目:
人称“AC女之杀手”的超级偶像LELE最近忽然玩起了深沉,这可急坏了众多“Cole”(LELE的粉丝,即”可乐”),经过多方打探,某资深Cole终于知道了原因,原来,LELE最近研究起了著名的RPG难题:
有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色.求全部的满足要求的涂法.
以上就是著名的RPG难题.
如果你是Cole,我想你一定会想尽办法帮助LELE解决这个问题的;如果不是,看在众多漂亮的痛不欲生的Cole女的面子上,你也不会袖手旁观吧?
Input
输入数据包含多个测试实例,每个测试实例占一行,由一个整数N组成,(0 < n<= 50)。
Output
对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。
Sample Input
1
2
Sample Output
3
6
思路:
这题我没找到递推式,但是我打了个表找了个规律…….用dfs暴搜打了个表,发现要么2*f[i-1]+6,
2*[f-1]-6…..
其实仔细想一想就可以得出:当直到前n-1项的 不同的排列数,这个时候如果第n-1项和第一项相同,那么第n项就有两种可能,如果不同,就只有一种可能,也即是:
f[i] = f[i-1] + 2*f[i-2];
代码:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define LL long longLL s[55];int main(){ s[1] = 3; s[2] = 6; s[3] = 6; for(int i = 4; i < 55; i++) { if(i%2 == 0) s[i] = s[i-1]*2+6; else s[i] = s[i-1]*2-6; } int n; while(~scanf("%d",&n)) { printf("%I64d\n",s[n]); } return 0;}
//hdu2046
题目:
在2×n的一个长方形方格中,用一个1× 2的骨牌铺满方格,输入n ,输出铺放方案的总数.
例如n=3时,为2× 3方格,骨牌的铺放方案有三种,如下图:
Input
输入数据由多行组成,每行包含一个整数n,表示该测试实例的长方形方格的规格是2×n (0 < n <= 50)。
Output
对于每个测试实例,请输出铺放方案的总数,每个实例的输出占一行。
Sample Input
1
3
2
Sample Output
1
3
2
思路:假设知道前n-1项的不同的排列和,那么第n个,我们会发现,只有两种情况,一种是前n-2项的排列数,然后横着堆俩块,另一种是前n-1项的,竖着堆一块。
a[i] = a[i-1] + a[i-2];
代码:
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define LL long longLL a[55];int main(){ a[1] = 1; a[2] = 2; for(int i = 3; i <= 50; i++) a[i] = a[i-1] + a[i-2]; int n; while(~scanf("%d",&n)) { printf("%I64d\n",a[n]); } return 0;}
hdu2047
题目大意: 由EOF三种字符组成长度为n的字符串,要求两个O不能相邻,求共有多少种方法。
思路:想的方法很奇怪,我把有O为结尾的分为了一组,没有O结尾的分为了一组,这样就好想了。
其实不用三个数组的话,是可以这样的,知道前n-1的ans值,固定第n项为O时,n
-1项不能为O,就有2*ans[i-2],如果n项不是O,那么就是2*ans[i-1];,即
ans[i] = 2*ans[i-2] + 2*ans[i-1];
代码:
#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define LL long longLL have0[50];LL nothave[50];LL ans[50];int main(){ have0[1] = 1; have0[2] = 2; nothave[1] = 2; nothave[2] = 6; ans[1] = 3; ans[2] = 8; for(int i = 3; i < 50; i++) { ans[i] = have0[i-1] * 2 + nothave[i-1] * 3; have0[i] = nothave[i-1]; nothave[i] = ans[i] - have0[i]; } int n; while(~scanf("%d",&n)) { printf("%I64d\n",ans[n]); } return 0;}
hdu2048
题目大意: n个数字的错排问题。
思路: 知道d[1] 到 d[n-1], 此时的第n个人有两种情况,一种是拿到了自己的号,这时与前面任意一人换即可,即(n-1)*d[n-1], 若不是拿的自己的,则前面必有一个人拿的第n号,而剩下的n-2人必须满足错排列,故有(n-1)*d[n-2];
d[n] = (n-1)*(d[n-1] + d[n-2]);
#include <cstdio>#include <iostream>using namespace std;#define LL long longLL fac[20];LL f[20];int main(){ fac[1] = 1; for(int i = 2;i <= 20; i++) { fac[i] = i*fac[i-1]; //cout<<fac[i]<<endl; } f[1] = 0; f[2] = 1; f[3] = 2; for(int i = 4; i <= 20; i++) f[i] = (i-1)*(f[i-1]+ f[i-2]); int n,t; scanf("%d",&t); while(t--) { scanf("%d",&n); cout<<f[n]<<' '<<fac[n]<<endl; double ans = (double)f[n]*100/fac[n]; printf("%.2f%%\n",ans); } return 0;}
hdu2049
题目大意: n个数里m个数错排
思路: 上一题已经知道错排怎么求了,所以这一题就是Cmn * d[m];这题数组还开小了一个…简直智障…
代码:
#include <cstdio>#include <cstring>#include <iostream>using namespace std;#define LL long longLL f[25];LL fac[25];int main(){ fac[0] = 1; fac[1] = 1; f[1] = 0; f[2] = 1; f[3] = 2; for(int i = 2; i <= 20; i++) { fac[i] = i*fac[i-1]; // cout<<fac[i]<<endl; } for(int i = 4; i <= 20; i++) { f[i] = (i-1)*(f[i-1]+f[i-2]); } int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); LL x = fac[n]/fac[n-m]/fac[m]; // cout<<x<<endl; cout<<x*f[m]<<endl; } return 0;}
hdu2050
题目: 问n条折线能将平面分为多少份
我空间想象力差的不是一点半点。。。
代码:
#include <cstdio>#include <cstring>using namespace std;#define LL long longLL data[10005];int main(){ data[1] = 2; for(int i = 2; i < 10005; i++) data[i] = data[i-1] + 4*(i-1) + 1; int t,n; scanf("%d",&t); while(t--) { scanf("%d",&n); printf("%I64d\n",data[n]); } return 0;}
- 递推求解专题训练
- 寒假训练 递推专题
- HDU-#2044-2050 递推求解专题
- ACM训练赛--递推专题
- hdu 2044-2050 递推求解专题练习
- HDU 2041--超级楼梯题解(递推求解专题)
- Hdu递推求解专题练习(For Beginner)
- 递推求解专题练习(For Beginner) 【hdu】
- 递推求解专题练习(For Beginner)
- 【专题训练】【递推算法】 单峰排列 解题报告
- 递推求解
- 简谈--递推求解
- 递推求解
- HDU 2047--阿牛的EOF牛肉串(递推求解专题)
- 递推求解专题练习(For Beginner) 折线分割平面 HDU 2050
- HDU 递推求解专题练习 2045 2046 2047 2048 2049 2050
- 递推专题
- HDU 递推专题
- 机器学习笔记(三) 朴素贝叶斯分类
- 拍卖(京东2017实习生招聘真题)
- url中文乱码
- c# 设计模式-单例模式
- python学习笔记(四)模块、面向对象
- 递推求解专题训练
- Pyhon 网络爬虫--简单的爬取功能
- 判断元素在数组中出现的次数
- 高德地图应用试开发--第二版(百度试验号已阵亡)
- 文章标题
- Maven Spring MVC + MyBatis 开发配置
- mysql数据库常用sql的分类整理
- HashMap集合
- C++:new和delete的用法