anboni: try to look at A* algorithm (
http://en.wikipedia.org/wiki/A%2A_search_algorithm) and think more about how it can be improved to achieve what you like. Unfortunatelly it has no way how to compare 2 routes and decide. It can only choose betwen two tracks when it reaches junction, but at this moment it has no idea which one leads to the destination. Later on, when binary heap (open list) gives next node to search it follows that node. Everything depends on comparison of cost estimate of nodes. Cost estimate is sum of cost from origin (train's current position) up to the node and distance of that node from destination. Like:
node.estimate = node.cost(org, node) + node.distance(node, destination)
The cost() calculation it the only thing we can play with if it shoul be still A*. In current implementation there is also one very important rule that we must care about: When you follow node to the next node (first one is parent, new one child), the child.estimate must not be less than parent.estimate (maybe you remember one very common
assert(n.m_estimate >= n.m_parent->m_estimate).
In other words it meand that real single node cost must be equal or higher than distance between two nodes (child, parent). If you for example apply negative penalty for down-hill tile, you break this rule and run into problems.
On the other side, any positive penalty (like up-hill move) makes bigger and bigger difference between estimate and real cost of whole path and A* becomes less and less effective. In worst case it can be as ineffective as dijkstra algorithm (
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm).
So try to formulate your idea in relation to this. Otherwise we will not talk about improvement but about different pathfinding algorithm. This can be also good, but more time consuming.