第一行——咕咕咕。
第二行——不吃早饭的后果是会饿,连续不吃早饭的后果是养成了到点儿就饿的生物钟。别问,问就是在想中午吃点啥。啊啊啊怀念七月上旬醒来就有饭吃的日子qwq
第三行——昨天请了十分钟的假,sj师哥很爽快(此处存疑)地答应了,然后下一句是
咱也不知道怎么回事咱也不敢反驳.jpg
于是——
但是我真的不会dp啊qwq以前遇到这样的题基本都是略过的呢(委屈巴巴.jpg),于是您可以看到一个疯狂想递推公式就是想不出来,一上午做不了一个dp的人欲哭无泪。
但刚好趁这个机会练习dp了,嗯嗯迎难而上(滑稽.jpg)。
sj师哥是个好队长(疯狂点头.jpg)
1.SDNU1044
这道题的坑点是“花在花瓶中的先后顺序必须与给定顺序相同”,也就是说,当第j个瓶放了第i朵fafa后,第i+1朵fafa就只能放在第j+1及其之后的瓶了。
递推公式:
for(int i = 1; i <= n; ++i)//花
for(int j = 1; j <= m; ++j)//瓶
{
if(i > j)
continue;
else
dp[i][j] = max(dp[i-1][j-1]+a[i][j],dp[i][j-1]);
}
2.HDU1087
思路:用dp[i]存最后一步到dp[i]时候的最大值,外层是初始化为一步的值,内层是判断前面有没有可以跳的点(满足当前点大于上一个可跳的点),更新dp的值。
没发现有啥坑。
记得最后再跑一次循环找max。
递推公式:
for(int i = 0; i < n; ++i)
{
dp[i] = a[i];
for(int j = 0; j < i; ++j)
{
if(a[i] > a[j])
dp[i] = max(dp[i],dp[j]+a[i]);
}
}
SDNU1330这个跟2一样。
3.HDU1114
思路:用dp存放满i容量时最少的钱数,枚举钱的cost和value找最小
递推公式:
for(int i = 1; i <= volume; ++i)
{
for(int j = 0; j < n; ++j)
{
if(i-c[j] >= 0)
{
dp[i] = min(dp[i],dp[i-c[j]]+v[j]);
}
}
}
4.SDNU1038
思路:只能向右向下,所以当前点可由上一行的同列或同一行的前一列递推过来。
递推公式:
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
dp[i][j] = max(dp[i-1][j],dp[i][j-1])+tu[i][j];
}
}
思路:1.用dp[i][j]表示到有i个Aj个B的时候的方案数
2.dp[i][j]可以由dp[i-1][j]和dp[i][j-1]得到
3.利用贪心的策略,前n个A一定为AB的A,前m个B一定为BA的B,便于其组成AB和BA
4.i个A的时候,只要是前面的A小于n个或者多出来的A比前面的B少,就放A。用min(m,j)是因为最多前面放m个B,当i为n时且前面没有B时就不能再放A了
5.j个B时同理,组成的BA小于m或者前面的B比A少时就放B
下附状态转移方程
dp[0][0] = 1;
for(int i = 0; i <= n+m; ++i)
for(int j = 0; j <= m+n; ++j)
{
if(i < n || (i-n) < min(m,j))
dp[i+1][j] = (dp[i+1][j] + dp[i][j])%mod;
if(j < m || (j-m) < min(n,i))
dp[i][j+1] = (dp[i][j+1] + dp[i][j])%mod;
}
欢迎指出错误qwq
dp杀我!