每次被动态规划的问题给搞死掉!
所以打算每次把dp转移的方程写下来! 然后慢慢积累吧! 也希望分享给大家!
动态规划第一题
题目传送门:哈尔滨工程大学第十四届程序设计竞赛(同步赛)F题
题意: 一个迷宫,然后从(1,1)走到(n,n),只能往下或者右边走!然后每次走的map【i】【j】表示的就是你需要花费这么多代价,然后每次换一个方向,
小帆帆第一次改变方向的费用是 1,第二次的费用是 2,第三次的费用是
4,…… 第 K 次的费用是2^(?−1)。
思路: 我一开始是bfs!然后呢WA,最后看了下dp解。。。
dp[x][y] [ 转移的次数 ][方向的状态]: 表示的就是走到(x,y)位置转移方向k次的最小花费!
所以有: dp[i][j][k][0] = min(dp[i-1][j][k][0],dp[i][j-1][k-1][1]+(1<<k-1))+maps[i][j];
AC代码:
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
int read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
ll minn(ll a, ll b){
if(a>b){
return b;
}else{
return a;
}
}
int ans,n;
int sa[105][105];
// dp[x][y][转移次数][方向]
// dp[i][j][k][0/1] 表示的是到 (i,j)的位置 变换k次方向的时候 最小话费 0 1 表示的就是方向
int dp[105][105][25][2];
int main(){
int t;
t = read();
int k =3;
while(t--){
ans = 2e9;
n = read();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
sa[i][j] = read();
memset(dp,0x3f3f,sizeof(dp));
// 初始化为 注意边界就行
dp[1][1][0][1] = dp[1][1][0][0] =sa[1][1];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++){
if(i == 1&&j ==1) continue;
int cc = sa[i][j];
dp[i][j][0][0] = dp[i-1][j][0][0] +cc;
dp[i][j][0][1] = dp[i][j-1][0][1] +cc;
for(int k = 1; k<=24; k++){
dp[i][j][k][0] = min(dp[i-1][j][k][0],dp[i][j-1][k-1][1]+(1<<k-1))+cc;
// 当前的位置的最小值 就是前面同一个方向 或者是不同的方向 那么就该加上 1<<k-1
dp[i][j][k][1] = min(dp[i][j-1][k][1],dp[i-1][j][k-1][0]+(1<<k-1))+cc;
}
}
for(int i = 0; i <=24; i++){
ans = minn(ans,minn(dp[n][n][i][1],dp[n][n][i][0])); //这里就是求最后的(n,n)位置,但是不知道是方向方向,还有转了多少次的方向
}
cout<<ans<<endl;
}
return 0;
}
动态规划第二题
动态规划第一题
题目传送门:西北大学集训队选拔赛(重现赛)B题拯救地球(动态规划)
题意: 告诉你有n个救援队,然后m个发动机坏了,需要去救援至少k个,才算是成功,然后每个救援队成功的概率是p,求最后成功概率
思路: 当然就是写出转态转移方程,dp【i】【j】表示的就是到第i个发动机的时候,成功启动j个发动机的概率,然后…(一个发动机成功概率:1-所有救援队失败的概率)
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;
void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
double dp[2005][2005];
int main(){
int n, m, k, x;
double cc;
double sa[2005];
read(n), read(m), read(k);
for(int i = 1; i <= m; i++) sa[i] = 1.0;
for(int i = 1; i <= n; i++){
cin>>x>>cc;
sa[x] =sa[x] *(1-cc);
}
for(int i = 1; i <= m; i++) sa[i] = 1.0 - sa[i];
dp[0][0] = 1;
for(int i = 1; i <= m; i++){
dp[i][0] = dp[i-1][0] *(1-sa[i]);
for(int j = 1; j <= m; j++){ //一共就m个机器
dp[i][j] = dp[i-1][j-1]*sa[i] + dp[i-1][j]*(1-sa[i]);
}
}
double ans = 0;
for(int i = k; i <= m; i++){
ans += dp[m][i];
}
printf("%.3lf\n",ans);
return 0;
}
博主分享动态规划的学习心得,通过记录每次遇到的dp问题及转移方程进行积累。文章中包含两道动态规划题目,分别是哈尔滨工程大学第十四届程序设计竞赛的F题和西北大学集训队选拔赛的B题,解析了题意和解题思路,并提供了AC代码。博主强调了dp状态转移在解决这类问题中的重要性,并表示会持续更新更多题目。
1734

被折叠的 条评论
为什么被折叠?



