版权声明: https://blog.csdn.net/King8611/article/details/82560866
题目链接:https://nanti.jisuanke.com/t/31454
题目大概意思:
刚才写这篇博客的时候,把意思打出来了,结果不小心关了,然后没保存上。这次就不解释了。
大概思路:
比较难想,但是想到了就不难了。
就是一个dfs+记忆数组,然后把搜索过的结果存起来,方便下次用。
复杂度:n*200
代码:
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;
public class Main {
static int sum=0;
static int arr[][];
static int n,m,k,l;
static int dp[][]; //一个dp记忆搜索过的路线,防止超时
static int inf=Integer.MAX_VALUE;
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static void main( String args[])throws Exception{
//因为分数会出现负数,为了避免这个情况,分数相关的数据+100就行了
n=getInt();
m=getInt()+100;
k=getInt()+100;
l=getInt()+100;
arr=new int[n][3];
dp=new int[n][301];
for(int i=0;i<n;i++)
for(int j=0;j<300;j++)
dp[i][j]=inf;
for(int i=0;i<n;i++)
for(int j=0;j<3;j++)
arr[i][j]=getInt();
int ans=dui(0,m);
if(ans>=k)
System.out.println("Good Ending");
else if(ans<=l)
System.out.println("Bad Ending");
else
System.out.println("Normal Ending");
}
static int dui(int i,int now) { //一个伟大的dfs,不要以为他超时
//i表示第i次操作,now表示当前的分数。
if(i==n)
return now;
if(dp[i][now]!=inf) //如果更新过这个点,那就没必要往下继续更新了,就要换线路了。
return dp[i][now];
if(i%2==0) { //第一个人拿的情况
int ans=-100;
//搜索三个情况可能出现的所有结果
if(arr[i][0]>0) {
int nn=Math.min(now+arr[i][0],200);
ans=Math.max(ans, dui(i+1,nn)); //第一个人当然是想拿最大啦
}
if(arr[i][1]>0) {
int nn=Math.max(now-arr[i][1], 0);
ans=Math.max(ans, dui(i+1,nn));
}
if(arr[i][2]>0) {
ans=Math.max(ans, dui(i+1,200-now));
}
dp[i][now]=ans;
return ans; //储存当前的情况,可以保证二次利用,以防超时。
} //第二个人想要最小,和第一个类似
else {
int ans=200;
if(arr[i][0]>0) {
int nn=Math.min(now+arr[i][0],200);
ans=Math.min(ans, dui(i+1,nn));
}
if(arr[i][1]>0) {
int nn=Math.max(now-arr[i][1], 0);
ans=Math.min(ans, dui(i+1,nn));
}
if(arr[i][2]>0) {
ans=Math.min(ans, dui(i+1,200-now));
}
dp[i][now]=ans;
return ans;
}
}
static int getInt() throws IOException{
in.nextToken();
return (int) in.nval;
}
}