原题请参考poj 1661
思路:先用一个struct将板子表示出来,再按高度对他们进行排序,
问题简化为对板子的处理。
mintime=下落时间+min{向左走最小时间,向右走最小时间};
同时进行动态规划,将时间存在两个数组中
#include<iostream>
#include<algorithm>using namespace std;
const int manx = 40001;
struct Block{
int X1,X2,H;
};
bool compare(Block b1,Block b2){
return b1.H > b2.H;
}
Block blocks[manx];
int fall(int X,int Y,int maax);
int leftTime[manx + 10];
int rightTime[manx + 10];
int leftMinTime(int k);
int rightMinTime(int k);
int leftWhetherDown(int k);
int rightWhetherDown(int k);
int n,X,Y,maax;
int main(){
int t;
scanf("%d",&t);
while(t--)
{
memset(leftTime,-1,sizeof(leftTime));
memset(rightTime,-1,sizeof(rightTime));
cin>>n>>X>>Y>>maax;
blocks[0].X1 = blocks[0].X2 = X;
blocks[0].H = Y;
for(int i = 1;i <= n;i++)
{
scanf("%d%d%d",&blocks[i].X1,&blocks[i].X2,&blocks[i].H);
}
sort(blocks+1,blocks+n+1,compare);
int minTime = min(leftMinTime(0),rightMinTime(0));
printf("%d\n",minTime);
}
return 0;
}
int leftMinTime(int k){
int result(0);
int tmp = leftWhetherDown(k);
if(tmp == 0 )
{
if(blocks[k].H > maax)
return 1000000;
else
return blocks[k].H;
}
else
{
if(blocks[k].H - blocks[tmp].H > maax)
return 10000000;
int Ltmp,Rtmp;
if(leftTime[tmp] != -1)
Ltmp = leftTime[tmp];
else
Ltmp = leftMinTime(tmp);
if(rightTime[tmp] != -1)
Rtmp = rightTime[tmp];
else
Rtmp = rightMinTime(tmp);
result = (blocks[k].H - blocks[tmp].H) +
min((blocks[k].X1 - blocks[tmp].X1 + Ltmp),(blocks[tmp].X2 - blocks[k].X1 + Rtmp));
}
leftTime[k] = result;
return result;
}
int rightMinTime(int k){
int result(0);
int tmp = rightWhetherDown(k);
if(tmp == 0 )
{
if(blocks[k].H > maax)
return 1000000;
else
return blocks[k].H;
}
else
{
if(blocks[k].H - blocks[tmp].H > maax)
return 10000000;
result = (blocks[k].H - blocks[tmp].H) +
min((blocks[k].X2 - blocks[tmp].X1 + leftMinTime(tmp)),(blocks[tmp].X2 - blocks[k].X2 + rightMinTime(tmp)));
}
rightTime[k] = result;
return result;
}
int leftWhetherDown(int k){
int i,result(0);
for(i = k + 1;i <= n;i++)
{
if((blocks[i].X1 <= blocks[k].X1) && (blocks[i].X2 >= blocks[k].X1))
{
result = i;
break;
}
}
return result;
}
int rightWhetherDown(int k){
int i,result(0);
for(i = k + 1;i <= n;i++)
{
if((blocks[i].X1 <= blocks[k].X2) && (blocks[i].X2 >= blocks[k].X2))
{
result = i;
break;
}
}
return result;
}
递推算法(程序设计实习答案)
///
//递推的程序:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAX_N 1000
#define INFINITE 1000000
int t,n,x,y,maxHeight;
struct Platform{
int Lx, Rx, h;
bool operator < (const Platform & p2) const {
return h > p2.h;
}
};
Platform platforms[MAX_N + 10];
int leftMinTime[MAX_N + 10]; //各板子从左走最短时间
int rightMinTime[MAX_N + 10]; //各板子从右走最短时间
int main()
{
scanf("%d",&t);
while( t--) {
scanf("%d%d%d%d",&n, &x, &y, &maxHeight);
platforms[0].Lx = x; platforms[0].Rx = x; platforms[0].h = y;
for( int j = 1; j <= n; j ++ )
scanf("%d%d%d",&platforms[j].Lx,& platforms[j].Rx,
& platforms[j].h);
sort(platforms,platforms+n+1);
for( int i = n ; i >= 0; -- i ) {
int j;
for( j = i + 1; j <= n ; ++ j ) { //找i的左端的下面那块板子
if( platforms[i].Lx <= platforms[j].Rx
&& platforms[i].Lx >= platforms[j].Lx)
break;
}
if( j >n ) { //找不到
if( platforms[i].h > maxHeight )
leftMinTime[i] = INFINITE;
else
leftMinTime[i] = platforms[i].h;
}
else {
int y = platforms[i].h - platforms[j].h;
if( y > maxHeight)
leftMinTime[i] = INFINITE;
else
leftMinTime[i] = y +
min(leftMinTime[j]+platforms[i].Lx-platforms[j].Lx,
rightMinTime[j]+platforms[j].Rx-platforms[i].Lx);
}
for( j = i + 1; j <= n ; ++ j ) { //找i的右端的下面那块板子
if( platforms[i].Rx <= platforms[j].Rx
&& platforms[i].Rx >= platforms[j].Lx)
break;
}
if( j > n ) {
if( platforms[i].h > maxHeight )
rightMinTime[i] = INFINITE;
else rightMinTime[i] = platforms[i].h;
}
else {
int y = platforms[i].h - platforms[j].h;
if( y > maxHeight) rightMinTime[i] = INFINITE;
else
rightMinTime[i] = y +
min(leftMinTime[j]+platforms[i].Rx-platforms[j].Lx,
rightMinTime[j]+platforms[j].Rx-platforms[i].Rx);
}
}
printf("%d\n", min(leftMinTime[0],rightMinTime[0]));
}
return 0;