记忆化搜索入门题——滑雪POJ-1088+多段图最短路UVA-116+买可乐UVA-10626

滑雪

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int dp[110][110],a[110][110];
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
int m,n;
int dfs(int x,int y){
    if(dp[x][y]>=0) return dp[x][y];
    int cnt=1;
    for(int i=0;i<4;i++){
        int nx = x+dx[i],ny = y+dy[i];
        if(nx>=1 && nx<=m && ny>=1 && ny<=n && a[x][y]>a[nx][ny]){
            cnt =  max(dfs(nx,ny)+1,cnt);
        }
    }
    dp[x][y] = cnt;
    return dp[x][y];
}


int main(){
    cin>>m>>n;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    memset(dp, -1, sizeof(dp));
    int ans = 1;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            ans = max(ans,dfs(i, j));
        }
    }
    printf("%d\n",ans);
    return 0;
}

多段图最短路

(下面的代码并没有进行路径记录)

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int inf = (1<<30)+1000;
int m,n,map[15][105],path[15][105],d[15][105];

int dfs(int x,int y)
{
    if(d[x][y]<inf) return d[x][y];
    if(y==n) return d[x][y]=map[x][y];
    int op[] = {x,x-1,x+1};
    if(x==1) op[1]=m;
    if(x==m) op[2]=1;
    int &res = d[x][y];
    for(int k=0;k<3;k++)
    {
        int cost = map[x][y]+dfs(op[k],y+1);
        res = min(cost,res);
    }
    return res;
}

int main(){
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&map[i][j]);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                d[i][j] = inf;
        int ans = inf;
        for(int i=1;i<=m;i++)
            ans = min(ans,dfs(i,1));
        printf("%d\n",ans);
    }
    return 0;
}

两道题其实都是在DAG上求最长路(最短路的题目)
对比:
搜索起点:
一个是不确定的,一个是第一列。
搜索终点:
一个是仍是不确定的,一个是最后一列。
方案选择:
一个是上下左右,一个是右上,右,右下。
目标答案:
一个是全图求max,一个是第一列求最小值。

买可乐

买可乐时的方案就对应下面的五条if语句。
尤其是,用1个10元和3个一元买一个可乐,找1个5元的情况。
注意,题目不允许一次性买多个可乐。

    if(c>=1) m=min(m,dfs(cnt+1, a+2, b, c-1)+1);
    if(b>=2) m=min(m,dfs(cnt+1, a+2, b-2, c)+2);
    if(b>=1&&a>=3) m=min(m,dfs(cnt+1, a-3, b-1, c)+4);
    if(c>=1&&a>=3) m=min(m,dfs(cnt+1, a-3, b+1, c-1)+4);
    if(a>=8) m=min(m,dfs(cnt+1,a-8,b,c)+8);
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int ncase,dp[1000][200][60],m,n1,n5,n10;;
int dfs(int cnt,int a,int b,int c){
    if(dp[a][b][c]>0) return dp[a][b][c];
    if(cnt==m) return dp[a][b][c]=0;
    int m(INF);
    if(c>=1) m=min(m,dfs(cnt+1, a+2, b, c-1)+1);
    if(b>=2) m=min(m,dfs(cnt+1, a+2, b-2, c)+2);
    if(b>=1&&a>=3) m=min(m,dfs(cnt+1, a-3, b-1, c)+4);
    if(c>=1&&a>=3) m=min(m,dfs(cnt+1, a-3, b+1, c-1)+4);
    if(a>=8) m=min(m,dfs(cnt+1,a-8,b,c)+8);
    return dp[a][b][c]=m;
}

int main(){
    cin>>ncase;
    while(ncase--){
        scanf("%d%d%d%d",&m,&n1,&n5,&n10);
        memset(dp,-1,sizeof(dp));
        printf("%d\n",dfs(0, n1, n5, n10));
    }
    return 0;
}
发布了67 篇原创文章 · 获赞 0 · 访问量 1506

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/104581562