计蒜客—逃生

代码:四次dp显得代码有点多,可以用向量一次解决,需要点技巧。代码核心思路可以看看,不是太好

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
ll n,m,x,y,v,c;
ll a[1005][1005],mark[1005][1005],dp[1005][1005];
ll mx=0,flag=0;
int deal1(ll zx,ll zy){
	for(int j=1;j<=y;j++)mark[x+1][j]=-1;
	for(int i=1;i<=x;i++)mark[i][y+1]=-1;
	for(int i=x;i>=1;i--)
	  for(int j=y;j>=1;j--){
	  	 ll temp1=0,temp2=0;
	    if(i==x&j==y){
		    dp[x][y]=(v>c)?c:v;continue;
		 }
	     if(mark[i+1][j]==-1&&mark[i][j+1]==-1){
	     	 mark[i][j]=-1;
	     	 continue;
		 }
	     if(!mark[i+1][j])temp1=dp[i+1][j]+a[i][j];
		 if(!mark[i][j+1])temp2=dp[i][j+1]+a[i][j];
		 if(max(temp1,temp2)>c)dp[i][j]=c;
		 else if(max(temp1,temp2)<=0)mark[i][j]=-1;
		 else dp[i][j]=max(temp1,temp2);
	  }
	  if(mark[zx][zy]==-1)return 0;
	  else {
	  	flag=1;
	  	return dp[zx][zy];
	  }
}
int deal2(ll zx,ll zy){
	for(int j=1;j<=y;j++)mark[x-1][j]=-1;
	for(int i=x;i<=n;i++)mark[i][y+1]=-1;
	for(int i=x;i<=n;i++)
	  for(int j=y;j>=1;j--){
	  	 ll temp1=0,temp2=0;
	     if(i==x&j==y){
		    dp[x][y]=v>c?c:v;continue;
		 }
	     if(mark[i-1][j]==-1&&mark[i][j+1]==-1){
	     	 mark[i][j]=-1;
	     	 continue;
		 }
	     if(!mark[i-1][j])temp1=dp[i-1][j]+a[i][j];
		 if(!mark[i][j+1])temp2=dp[i][j+1]+a[i][j];
		 if(max(temp1,temp2)>c)dp[i][j]=c;
		 else if(max(temp1,temp2)<=0)mark[i][j]=-1;
		 else dp[i][j]=max(temp1,temp2);
	  }
	  if(mark[zx][zy]==-1)return 0;
	  else {
	  	flag=1;
	  	return dp[zx][zy];
	  }
}
int deal3(ll zx,ll zy){
	for(int j=y;j<=m;j++)mark[x+1][j]=-1;
	for(int i=1;i<=x;i++)mark[i][y-1]=-1;
	for(int i=x;i>=1;i--)
	  for(int j=y;j<=m;j++){
	  	 ll temp1=0,temp2=0;
	     if(i==x&j==y){
		    dp[x][y]=v>c?c:v;continue;
		 }
	     if(mark[i+1][j]==-1&&mark[i][j-1]==-1){
	     	 mark[i][j]=-1;
	     	 continue;
		 }
	     if(!mark[i+1][j])temp1=dp[i+1][j]+a[i][j];
		 if(!mark[i][j-1])temp2=dp[i][j-1]+a[i][j];
		 if(max(temp1,temp2)>c)dp[i][j]=c;
		 else if(max(temp1,temp2)<=0)mark[i][j]=-1;
		 else dp[i][j]=max(temp1,temp2);
	  }
	  if(mark[zx][zy]==-1)return 0;
	  else {
	  	flag=1;
	  	return dp[zx][zy];
	  }
}
int deal4(ll zx,ll zy){
	for(int j=y;j<=m;j++)mark[x-1][j]=-1;
	for(int i=x;i<=n;i++)mark[i][y-1]=-1;
	for(int i=x;i<=n;i++)
	  for(int j=y;j<=m;j++){
	  	 ll temp1=0,temp2=0;
	     if(i==x&j==y){
		    dp[x][y]=v>c?c:v;continue;
		 }
	     if(mark[i-1][j]==-1&&mark[i][j-1]==-1){
	     	 mark[i][j]=-1;
	     	 continue;
		 }
	     if(!mark[i-1][j])temp1=dp[i-1][j]+a[i][j];
		 if(!mark[i][j-1])temp2=dp[i][j-1]+a[i][j];
		 if(max(temp1,temp2)>c)dp[i][j]=c;
		 else if(max(temp1,temp2)<=0)mark[i][j]=-1;
		 else dp[i][j]=max(temp1,temp2);
	  }
	  if(mark[zx][zy]==-1)return 0;
	  else {
	  	flag=1;
	  	return dp[zx][zy];
	  }
}
int main(){
	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];
	  }
     for(int i=1;i<=4;i++){
     	ll re;
     	memset(mark,0,sizeof(mark));
     	memset(dp,0,sizeof(dp));
     	if(i==1)re=deal1(1,1);
     	else if(i==2)re=deal2(n,1);
     	else if(i==3)re=deal3(1,m);
     	else re=deal4(n,m);
     	if(mx<re)mx=re;
	 }
	 if(flag)cout<<mx<<endl;
	 else cout<<-1<<endl; 
	 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值