引子:
在家里作业做完没事干,就看到了这道dp。以为比较简单,结果用掉了大半个下午。~~结果还是没有把状态转移方程推出来 ~~ 结果还是没有把状态转移方程推出来 所以想来总结总结。
题目
反思:
为什么我没有做起呢一部分原因是基础不好不知道该怎么下手去写,去想,还有一个原因就是没有真正的读懂题。就比如这一段话:
两种传球方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有三个同学11号、22号、33号,并假设小蛮为11号,球传了33次回到小蛮手里的方式有11->22->33->11和11->33->22->11,共22种。
没有搞懂他传球的原理是什么,所以难免显得会无从下手。
思路:
状态转移方程是:
f[i][j]=f[i-1][j-1]+f[i-1][j+1]
因为我们可以发现,任何一个位置都只能从左边和右边传过来,所以得来这个状态转移方程。这是什么意思呢?
如图所示:这是别人做的一个图我借鉴一下,更好理解
假设有假设有5个人,传6次球。
在初始情况下,小蛮手中必然有且只有一个球,记为1;
第一轮传球后,小明必然将手中的球传给2号或5号同学,于是这两个同学各有1的可能性;
第二轮传球后,(如果上一轮小明将球传给2号)2号同学必然将球传给小明或3号,(如果上一轮小明将球传给5号),5号同学必然将球传给小明或4号,于是小明有2种情况接到球(分别从2号和5号手中);
第三轮及其后以此类推…
所以这就是传球的原理,由此可以推出,假设初始情况为第0行,小明为第1列,从第1行开始:
f[i][j]=f[i-1][j-1]+f[i-1][j+1]
敲黑板(重点):
必须特判一下1和n!!为什么?
因为:
1只能传给n或者2
n只能传给n-1或1
其他都是j-1,j+1
所以我们要特判1和n
那么答案应该是存在dp[m][1]里的(因为最终传到小明那里)。
所以这就是我的代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[35][35],i,j,m,n;
int main()
{
scanf("%d%d",&n,&m);
dp[0][1]=1;
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
if(j==1)
dp[i][j]=dp[i-1][n]+dp[i-1][2];
else if(j==n)
dp[i][j]=dp[i-1][1]+dp[i-1][n-1];
else
dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1];
printf("%d",dp[m][1]);
return 0;
}
小结:
现在来说我们学的dp还算比较简单,应该多去刷一下比较经典的题多总结…战术性撤退