2015
07-16

# Slalom

You are competing in ski slalom, and you need to select an optimal path for the race to maximize the number of gates you can pass through.
There are N gates in total, and the gates can be considered as points. If you pass the left or the right of one gate, this gate should not be considered as a gate that you passed through. The ith gate occurs at distance yi down the hill, with the horizontal position of the ith gate given by xi. Each gate is further down the hill than the previous gate (i.e. yi < yi+1 for all i).
Your pairs of skis has speed vd (i.e. you move with a constant downward velocity of vd meters per second). Additionally, at any time you may move at a horizontal speed of at most vh meters per second.
You may start and finish at any two positions. Your task now is to calculate how many gates at most that you can pass through.

There is an integer T (1 <= T <= 1000) in the first line, which indicates there are T test cases in total.
For each test case, there are three integers N (1 <= N <= 30000), vd (1 <= vd <= 10000) and vh (1 <= vh <= 10000) in the first line, which have the same meaning as above. The following N lines each contain two integers xi (1 <= xi <= 1000000) and yi (1 <= yi <= 1000000), the horizontal and vertical positions respectively of the ith gate.
There are at most 10 test cases that satisfy N > 100.

There is an integer T (1 <= T <= 1000) in the first line, which indicates there are T test cases in total.
For each test case, there are three integers N (1 <= N <= 30000), vd (1 <= vd <= 10000) and vh (1 <= vh <= 10000) in the first line, which have the same meaning as above. The following N lines each contain two integers xi (1 <= xi <= 1000000) and yi (1 <= yi <= 1000000), the horizontal and vertical positions respectively of the ith gate.
There are at most 10 test cases that satisfy N > 100.

2
3 2 1
1 1
5 3
6 5
4 1 1
5 1
6 2
3 3
3 4

2
3
Hint
For Sample 1, you can select to pass through gate 2 and gate 3 to maximize the number of gates you passed through.
For Sample 2, you can select to pass through gate 1, gate 3 and gate 4 to maximize the number of gates you passed through.


http://acm.hdu.edu.cn/showproblem.php?pid=4418

#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
//#define LL __int64
#define LL long long
#define eps 1e-9
#define PI acos(-1.0)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 210;

double p[maxn];
double a[maxn][maxn];//增广矩阵
double X[maxn];//解集
int num[maxn];//给每个能给到达的point离散化
int n,m,x,y,d;
int equ,var,cnt;

bool Gauss()
{
int row,col,max_r,i,j;
row = 0;
col = 0;
while(row < equ && col < var)
{
max_r = row;
for(i = row+1; i < equ; i++)
{
if(fabs(a[i][col]) > fabs(a[max_r][col]))
max_r = i;
}
if(max_r != row)
{
for(j = col; j <= var; j++)
swap(a[row][j], a[max_r][j]);
}
if(fabs(a[row][col]) < eps)
{
col++;
continue;
}
for(i = row+1; i < equ; i++)
{
if(fabs(a[i][col]) < eps) continue;
double t = a[i][col]/a[row][col];
a[i][col] = 0.0;
for(j = col+1; j <= var; j++)
a[i][j] -= a[row][j]*t;
}
row++;
col++;
}

for(i = row; i < equ; i++)
if(fabs(a[i][var]) > eps)
return false; //无解
for(i = equ-1; i >= 0; i--)
{
if(fabs(a[i][i]) < eps) continue;
double t = a[i][var];
for(j = i+1; j < var; j++)
t -= a[i][j]*X[j];
X[i] = t/a[i][i];
}
return true;
}

void bfs(int s) //bfs找出所有能够到达的点并离散化
{
queue <int> que;
que.push(s);
num[s] = cnt++;
while(!que.empty())
{
int u = que.front();
que.pop();
for(int i = 1; i <= m; i++)
{
if(fabs(p[i]) < eps)
continue;
int v = (u+i)%n;
if(num[v] == -1)
{
num[v] = cnt++;
que.push(v);
}
}
}
}

int main()
{
int test;
scanf("%d",&test);
for(int item = 1; item <= test; item++)
{
scanf("%d %d %d %d %d",&n,&m,&y,&x,&d);
for(int i = 1; i <= m; i++)
{
scanf("%lf",&p[i]);
p[i] /= 100;
}
if(x == y)
{
printf("0.00\n");
continue;
}
n = 2*(n-1);
if(d == 1)
x = n-x;
memset(num,-1,sizeof(num));
cnt = 0;
bfs(x);
if(num[y] == -1 && num[n-y] == -1) //注意这里是 &&，只有当两个方向都走不到才算走不到
{
printf("Impossible !\n");
continue;
}

memset(a,0,sizeof(a));
memset(X,0,sizeof(X));
equ = var = cnt;

for(int i = 0; i < n; i++)
{
if(num[i] != -1)
{
if(i == y || i == n-y) //注意特判终点
{
a[num[i]][num[i]] = 1;
a[num[i]][cnt] = 0;
continue;
}
a[num[i]][num[i]] = 1;
for(int j = 1; j <= m; j++)
{
int t = (i+j)%n;
if(num[t] != -1)
a[num[i]][num[t]] -= p[j];
a[num[i]][cnt] += j*p[j];
}
}
}
if(Gauss())
printf("%.2lf\n",X[num[x]]);
else printf("Impossible !\n");
}
return 0;
}