好吧,这道题我交了第9次才A
我觉得想到动态规划不是一件很难的事情.....我在状态的定义上犯了一个错误
我一开始定义的状态是dp[i][j]表示坐标在i,j时的花费的最小时间,这就导致数组开不下,于是我就用了一个map来存
然后记忆化搜索当然就是记录4个值了i,j,当前下落的高度,以及是从哪个方向走过来的
就WA了4~5次....感觉这样行不通
然后就看了题解,发现应该把状态定义为dp[i][k]其中k是0或1表示在第i个平台上最左或是最右边跳下后用的最少时间
这样一来就好写很多了嘛
记忆化搜索的时候要额外加两个,一个初始的平台(x,x,y),一个是地面,其实我感觉地面不加也可以,特判一下。不过初始的需要加上,因为从初始的地方落下后不一定是落在第一个平台上,有可能是第二个或者后面的平台上(注,这儿的平台已经按照高度从大到小排了序)
眼睛漏看了n的范围,误以为题目没给,于是就用了vector。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
struct Node{
int x1,x2,h;
bool operator< (const Node& a)const{return h>a.h;}
explicit Node(int a=0,int b=0,int c=0):x1(a),x2(b),h(c){}
};
vector<Node> v;
vector<int> dp[2];
int n,x,y,m,t,ans,dfs(int x,int y);
int main(){
ios_base::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>n>>x>>y>>m;
v.resize(n);
dp[0].resize(n+1,-1);
dp[1].resize(n+1,-1);
for(int i=0;i<n;++i)
cin>>v[i].x1>>v[i].x2>>v[i].h;
v.push_back(Node(x,x,y));
sort(v.begin(),v.end());
v.push_back(Node(-0x3f3f3f3f,0x3f3f3f3f,0));
cout<<dfs(x,0)<<endl;
dp[0].clear();
dp[1].clear();
}
return 0;
}
int dfs(int x,int y){
if(y==v.size()-1)
return 0;
if(dp[0][y]!=-1&&dp[1][y]!=-1)
return min(x-v[y].x1+dp[0][y],v[y].x2-x+dp[1][y]);
dp[0][y]=dp[1][y]=0x3f3f3f3f;
for(int j=y+1;j<v.size()&&v[y].h-v[j].h<=m;++j){
if(v[y].x1>=v[j].x1&&v[y].x1<=v[j].x2){
dp[0][y]=min(dp[0][y],dfs(v[y].x1,j)+v[y].h-v[j].h);
break;
}
}
for(int j=y+1;j<v.size()&&v[y].h-v[j].h<=m;++j){
if(v[y].x2>=v[j].x1&&v[y].x2<=v[j].x2){
dp[1][y]=min(dp[1][y],dfs(v[y].x2,j)+v[y].h-v[j].h);
break;
}
}
return min(x-v[y].x1+dp[0][y],v[y].x2-x+dp[1][y]);
}