poj 1088 - 滑雪(dfs记忆化搜索)
题意:
中文题略
思路:
dp[i][j]表示到达(i,j)点的最长路径长度
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "string"
#include "cmath"
#include "queue"
#include "cstdio"
#include "algorithm"
#include "cctype"
#include "vector"
#include "map"
#include "stack"
using namespace std;
typedef long long LL;
const int INF = 0x6fffffff;
const int inf = 522133279;
const LL llinf = 1e30;
const double eps = 1e-10;
int g[110][110];
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int dp[110][110];
int x,y;
int maxc=-1;
int border(int xx , int yy)
{
return (xx >= 0 && xx < x) && (yy >= 0 && yy < y);
}
int dfs(int m , int n)
{
if(dp[m][n]) //已经有了最大值记录,避免重复计算
return dp[m][n];
int maxn = 0;
for(int i = 0 ; i < 4 ; i++)
{
int tmpx = m+dir[i][0];
int tmpy = n+dir[i][1];
if(border(tmpx,tmpy) && g[m][n] > g[tmpx][tmpy]) //获得最大值
dp[m][n] = max(dp[m][n] , dfs(tmpx,tmpy)+1);
}
return dp[m][n];
}
int main()
{
while(~scanf("%d%d" , &x,&y))
{
memset(dp,0,sizeof(dp));
for(int i = 0 ; i < x ; i++)
for(int j = 0; j < y ; j++)
scanf("%d",&g[i][j]);
for(int i = 0 ; i < x ; i++)
for(int j = 0; j < y ; j++)
maxc = max(maxc,dfs(i,j));
printf("%d\n",maxc+1);
}
return 0;
}
hdu 4800 - Josephina and RPG
题意:
有Size = C(3,m)种组合兵种(0开始编号),给出一个Size*Size的矩阵g,g[i][j]表示i组合打赢j组合的概率,如果某一组i打赢了j,i可以换成j的组合继续攻打敌人
给出一组N个组合的序列,问打赢它们的最大概率是多少
思路:
dp[i][j] 表示打败第i个组合之后我方当前队伍为j
order[i]表示第i组敌人的编号
状态转移方程:
dp[i][j] = max(dp[i-1][j]*g[j][order[i]] , dp[i][j]); 打败i-1的是j组合,仍旧用j去攻打i
dp[i][order[i]] = max(dp[i][order[i]] , dp[i-1][j] * g[j][order[i]]); 打败i-1的是j组合,接下来换成被j打败的order[i]兵种去攻打
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "string"
#include "cmath"
#include "queue"
#include "cstdio"
#include "algorithm"
#include "cctype"
#include "vector"
#include "map"
#include "stack"
using namespace std;
typedef long long LL;
const int INF = 0x6fffffff;
const int inf = 522133279;
const LL llinf = 1e30;
const double eps = 1e-10;
int M,N;
double g[200][200];
double dp[10010][200]; //dp[i][j] 打败第i个组合之后我方当前队伍为j
int order[10010];
int main()
{
while(~scanf("%d" , &M))
{
memset(dp,0,sizeof(dp));
int Size = (M-1)*(M-2)*M/6;
for(int i = 0 ; i < Size ; i++)
for(int j = 0 ; j < Size ; j++)
scanf("%lf" , &g[i][j]);
scanf("%d" , &N);
for(int i = 1 ; i <= N ; i++)
scanf("%d" , order+i);
for(int i = 0 ; i < Size ; i++)
dp[0][i] = 1;
for(int i = 1 ; i <= N ; i++)
for(int j = 0 ; j < Size ; j++)
{
dp[i][j] = max(dp[i-1][j]*g[j][order[i]] , dp[i][j]);
dp[i][order[i]] = max(dp[i][order[i]] , dp[i-1][j] * g[j][order[i]]);
}
double maxn = -1;
for(int i = 0 ; i < Size ; i++)
maxn = max(maxn,dp[N][i]);
printf("%.6lf\n" , maxn);
}
return 0;
}
hdu 2084 - 数塔(记忆化)
题意:
中文题略
思路:
dfs构造dp方程
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "string"
#include "cmath"
#include "queue"
#include "cstdio"
#include "algorithm"
#include "cctype"
#include "vector"
#include "map"
#include "stack"
using namespace std;
typedef long long LL;
const int INF = 0x6fffffff;
const int inf = 522133279;
const LL llinf = 1e30;
const double eps = 1e-10;
const int MOD=20121014;
int dp[110][110];
int g[110][110];
int n;
int dfs(int hang,int pos)
{
if(hang == n)
return g[hang][pos];
if(dp[hang][pos])
return dp[hang][pos];
return dp[hang][pos] = max(dfs(hang+1,pos), dfs(hang+1,pos+1))+g[hang][pos];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(dp,0,sizeof dp);
scanf("%d", &n);
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= i ; j++)
scanf("%d" , &g[i][j]);
printf("%d\n" , dfs(1,1));
}
return 0;
}
hdu 2571 - 命运
题意:
中文题略
思路:
还是记忆化,dfs构造特别清晰
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "string"
#include "cmath"
#include "queue"
#include "cstdio"
#include "algorithm"
#include "cctype"
#include "vector"
#include "map"
#include "stack"
using namespace std;
typedef long long LL;
const int INF = 0x6fffffff;
const int inf = 522133279;
const LL llinf = 1e30;
const double eps = 1e-10;
const int MOD=20121014;
int m,n;
int g[30][1100];
int dp[30][1100];
int dfs(int x , int y)
{
if(dp[x][y])
return dp[x][y];
if(x == m && y == n)
return g[m][n];
int maxc = -inf;
if(x < m)
maxc = max(maxc,dfs(x+1,y));
if(y < n)
maxc = max(maxc,dfs(x,y+1));
for(int i = 2 ; i*y <= n ; i++)
maxc = max(maxc,dfs(x,i*y));
return dp[x][y] = maxc + g[x][y];
}
int main()
{
int t;
scanf("%d" , &t);
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%d%d" , &m,&n);
for(int i = 1 ; i <= m ; i++)
for(int j = 1 ; j <= n ; j++)
scanf("%d",&g[i][j]);
printf("%d\n",dfs(1,1));
}
return 0;
}