计蒜客 逃生

在这里插入图片描述
样例输入

4 4 3 2 5 10
1 2 3 4
-1 -2 -3 -4
4 0 2 1
-4 -3 -2 -1

样例输出

10

思路
最开始是想的直接bfs暴力扩展,用优先队列存储节点,保证返回的一定是生命值最大的,并且在扩展时人为保证扩展方向,但是有几组数据没过,不知道哪里的方向没写对还是有一些小细节没注意到。
后面直接用动态规划去做,本来这道题就是动态规划问题,有三个原则:
1.如果是起点,则直接是初始值
2.如果x轴相同,那么就代表y的值发生了变化,就代表来自当前扩展方向的上一个行
3.如果y相同,那么就说明来自当前扩展方向的上一个列
4.如果x与y不同,那么就取上一行或者上一列的最大值
AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[1010][1010];
int dp[1010][1010];
int main(){
	int n,m,x,y,v,c;
	cin >> n >> m >> x >> y >> v >> c;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin >> a[i][j];
		}
	}
	int xx[4]={-1,-1,1,1};
	int yy[4]={-1,1,-1,1};
	for(int t=0;t<4;t++){
		for(int i=x;i>0&&i<=n;i-=xx[t]){
			for(int j=y;j>0&&j<=m;j-=yy[t]){
				if(i==x&&j==y){
					dp[i][j]=v;
				}//起点 
				else if(i==x){//同一列,那么就是y轴变化了 
					dp[i][j]=min(c,dp[i][j+yy[t]]+a[i][j]);
				}
				else if(i==y){//同一行,x变化 
					dp[i][j]=min(c,dp[i+xx[t]][j]+a[i][j]);
				}
				else{//既不同行也不同列,那么可能就是从上一行过来,或者上一列过来 
					dp[i][j]=min(c,max(dp[i+xx[t]][j],dp[i][j+yy[t]])+a[i][j]);
				}
				if(dp[i][j]<=0){
					dp[i][j]=-0x3f3f3f3f;
				}
			}
		}
	}
	int ans=max(dp[1][1],max(dp[n][1],max(dp[1][m],dp[n][m])));
	if(ans>0){
	cout << ans << endl;
	}else cout << -1 << endl; 
	return 0;
}

BFS未AC代码 记录一下我的自闭

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int g[1005][1005];
bool vis[4][1005][1005];
int dx[4][2]={{0,-1},{0,1},{0,-1},{0,1}};//左上,左下,右上,右下
int dy[4][2]={{-1,0},{-1,0},{1,0},{1,0}};
int n,m,x,y,v,c;
struct Node{
    int x;
    int y;
    int blood;
    Node(){};
    Node(int a,int b,int c){
        x=a;
        y=b;
        blood=c;
    }
    bool operator < (const Node &x)const{
        return blood<x.blood;
    }
};
bool check(int x,int y){
    if(x<=0||y<=0||x>n||y>m)return false;
    return true;
}
int bfs(int x,int y,int i){
    int exey[4][2]={{1,1},{n,1},{1,m},{n,m}};
    priority_queue<Node> pq;
    pq.push(Node(x,y,v+g[x][y]>c?c:v+g[x][y]));
    while(!pq.empty()){
        Node temp=pq.top();
        pq.pop();
       // cout << temp.x << " " << temp.y << " " << temp.blood << endl; 
        if(temp.x==exey[i][0]&&temp.y==exey[i][1]){
        	int kkk=temp.blood+g[temp.x][temp.y];
        	if(kkk>c)kkk=c;
            return kkk;
        }
        if(temp.blood<=0)continue;
        for(int j=0;j<2;j++){
            int ex=temp.x+dx[i][j];
            int ey=temp.y+dy[i][j];
            if(check(ex,ey)){
                if(vis[i][ex][ey])continue;
                vis[i][ex][ey]=true;
            	int sss=temp.blood+g[ex][ey];
            	if(sss>c)sss=c;
                pq.push(Node(ex,ey,sss));
            }
        }
    }
    return -1;
}
int main(){
    cin >> n >> m >> x >> y >> v >> c;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin >> g[i][j];
        }
    }
    int ans=-1;
    for(int i=0;i<4;i++){
    	int k=bfs(x,y,i);
    	//cout << k << endl;
        ans=max(ans,k);
    } 
    cout << ans << endl;
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值