首页 > ACM题库 > HDU-杭电 > HDU 4216-Computational Geometry?-动态规划-[解题报告]HOJ
2015
05-23

HDU 4216-Computational Geometry?-动态规划-[解题报告]HOJ

Computational Geometry?

问题描述 :

Computational geometry is a branch of computer science devoted to the study of algorithms which can be stated in terms of geometry. It often comes up with charming shapes and ideas.
In this problem, our poor princess is trapped in a castle by some bad guys again, yeah, again. So, let’s seize the chance to be a hero.
Right now, the beautiful princess is in the original point of a Cartesian coordinate system, for simplification, the castle is treated as a coordinate system, like a common computational geometry problem.
There is a bomb which can be exploded anytime, and it locates at (Xo, Yo) in the castle. To save the princess, we need design a route for her to leave away the bomb as far as possible. But she already has a plan written on her notebook, which contains some vectors, and she insists on escaping in the vectors’ direction one by one, that is, if she is in point(0, 0), and the vector is (X, Y), she will be in point(X, Y) if she escapes in this vector.
You get her notebook now, and find princess’s plan is a not a good plan sometimes. Then you decide to help the princess to make some slight modification, you can change the order of those vectors, and/or reverse some vectors, that is, change vector (X, Y) to vector (-X, -Y).
We want to know the maximum distance to the bomb after modification.

输入:

The first line contains a single integer T, indicating the number of test cases. Each test case begins with three integers N, Xo, Yo. Then N lines following, each line contains two integers, Xi and Yi, indicating a vector.Technical Specification
1. 1 <= T <= 100
2. 1 <= N <= 100
3. -100 <= Xi, Yi <= 100
4. -10 000 <= Xo, Yo <= 10 000

输出:

The first line contains a single integer T, indicating the number of test cases. Each test case begins with three integers N, Xo, Yo. Then N lines following, each line contains two integers, Xi and Yi, indicating a vector.Technical Specification
1. 1 <= T <= 100
2. 1 <= N <= 100
3. -100 <= Xi, Yi <= 100
4. -10 000 <= Xo, Yo <= 10 000

样例输入:

3
1 1 1
1 1
2 2 3
-1 2
1 -2
3 3 0
2 3
3 2
1 -1

样例输出:

Case 1: 2.828
Case 2: 7.000
Case 3: 9.849

 
题解:这个题目一眼看去像是贪心,但没想到竟是DP。
dp[i][j][0]表示前i个在纵坐标j处横坐标的最小值
dp[i][j][1]表示前i个在纵坐标j处横坐标的最大值
由当前状态向其他状态拓展即可。
#include
#include
#include
using namespace std;
#define D 10000
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
int num[105][2];
int dp[2][20005][2];
//dp[i][j][0] 前i个在纵坐标j处横坐标的最小值
//dp[i][j][1] 前i个在纵坐标j处横坐标的最大值
int T,n,x,y;
double dis(int a,int b)
{
double c=(double)a,d=(double)b;
return sqrt((c-x)*(c-x)+(d-y)*(d-y));
}
int main()
{
scanf("%d",&T);
for(int cas=1; cas<=T; ++cas)
{
scanf("%d%d%d",&n,&x,&y);
x+=D;
y+=D;
for(int i=1; i<=n; ++i)
{
scanf("%d%d",&num[i][0],&num[i][1]);
}
memset(dp,-1,sizeof(dp));
//初始化
dp[0][D][0]=dp[0][D][1]=D;
for(int i=1; i<=n; ++i)
{
for(int j=0; j<=20000; ++j)
for(int k=0; k<2; ++k)
{
if(dp[(i-1)&1][j][k]!=-1)
{
//更新dp[i][j+num[i][1]][0]最小值
if(dp[i&1][j+num[i][1]][0]==-1||dp[i&1][j+num[i][1]][0]>dp[(i-1)&1][j][k]+num[i][0])
dp[i&1][j+num[i][1]][0]=dp[(i-1)&1][j][k]+num[i][0];
//更新dp[i][j-num[i][1]][0]最小值
if(dp[i&1][j-num[i][1]][0]==-1||dp[i&1][j-num[i][1]][0]>dp[(i-1)&1][j][k]-num[i][0])
dp[i&1][j-num[i][1]][0]=dp[(i-1)&1][j][k]-num[i][0];
//更新dp[i][j+num[i][1]][0]最大值
if(dp[i&1][j+num[i][1]][1]==-1||dp[i&1][j+num[i][1]][1] dp[i&1][j+num[i][1]][1]=dp[(i-1)&1][j][k]+num[i][0];
//更新dp[i][j-num[i][1]][0]最大值
if(dp[i&1][j-num[i][1]][1]==-1||dp[i&1][j-num[i][1]][1] dp[i&1][j-num[i][1]][1]=dp[(i-1)&1][j][k]-num[i][0];
}
}
}
double dist=0.0;
//找距离最大值
for(int i=0; i<=20000; ++i)
for(int j=0; j<2; ++j)
if(dp[n&1][i][j]!=-1)
dist=max(dist,dis(dp[n&1][i][j],i));
printf(“Case %d: %.3f\n”,cas,dist);
}
return 0;
}

参考:http://blog.csdn.net/acm_ted/article/details/7842602