最小化矩阵中的总线更改次数

时间:2017-06-15 15:04:18

标签: algorithm path-finding backtracking

[ 42,  45,  47,  x,  x] -> stop1 to stop2
[ 45,  47,  42,  88,  x] -> stop2 to stop3
[ 21,  77,  42,  x,  x] -> stop3 to stop4
[ 22,  47,  42,  88,  x] -> stop4 to stop5
[ 23,  47,  42,  x,  x] -> stop5 to stop6
[ 24,  47,  42,  8,  91] -> stop6 to stop7
[ 25,  13,  42,  3,  84] -> stop7 to stop8
[ 26,  10,  11,  4,  54] -> stop8 to stop9
[ 27,  9,  8,  88,   71] -> stop9 to stop10

x is there just for formatting. The first row means that there are only three buses from stop1 to stop2(42, 45, 47).

我有这样的矩阵结构,其中每一行代表从一站到另一站的公共汽车。我需要尽量减少一个人从stop1到stop10所需的总线更改次数。

例如,其中一个输出应该是42,42,42,42,42,42,42,26,27,另一个可以是42,42,42,42,42,42,42,10,9。变化的次数超过三次我可以丢弃结果。

目前实现这一目标的最佳方式是什么,因为强制通过它是非常不合理的?

2 个答案:

答案 0 :(得分:2)

您可以通过将其建模为图搜索来解决此问题。

想象一下你是一个人而你正试图从A点到达B点。与你最相关的信息是

  1. 您目前所在的位置,
  2. 您目前所在的公交线路(如果有)。
  3. 因此,您可以将人的状态建模为一对位置(公共汽车站)和公交线路(可能是"不在线路上#34;当它们开始或结束时) 。因此,为位置和总线的每个组合创建一个包含一个节点的图形。

    此图中的边将对应于状态的变化。您可以通过

    更改状态
    1. 留在现有的公交线路上,或者去某个地方,或
    2. 切换公交线路。
    3. 如果您当前在公交线路上,如果线路从第一个位置移动到第二个位置,您可以保持该线路从一个位置移动到下一个位置。因此,如果总线 line 从location1转到location2,则创建边((location1, line ),(location2, line ))。这并不涉及转移,因此将此边缘的成本设为0。

      或者,您可以随时下车或从公共汽车下车到乘坐公共汽车。因此,为每一行和每个位置添加一条边((位置,线),(位置,免费))(您始终可以选择离开公交线路)并且给它成本0,因为这并不涉及改变线。同样,为给定位置的每条总线 line 添加边((location, free ),(location, line ))。给它1美元,表明这需要你乘坐公共汽车。

      现在,假设您在此图中找到了从(A点,免费)到(B点,免费)的路径。这对应于在A点开始并在B点结束的一系列总线的开启和关闭,并且成本将是您最终到达的不同总线的数量。如果您在此图表中运行最短路径算法(例如,Dijkstra算法),您将找到从起点到终点的路径,从而最大限度地减少总线传输次数!

答案 1 :(得分:1)

你可以通过一次数组,并保留一组常见的公共汽车。一旦找不到这样的公共汽车,就拿走前一套,从中选择一辆公共汽车,然后用那辆公共汽车填充结果。

然后将所有总线放在当前停止的集合中,并重复后续停止的操作,等等。

这是用ES6 JavaScript编码的算法。它使用public partial class CS : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!this.IsPostBack) { DataTable dt = this.GetData("SELECT ISNULL(AVG(Rating), 0) AverageRating, COUNT(Rating) RatingCount FROM UserRatings"); Rating1.CurrentRating = Convert.ToInt32(dt.Rows[0]["AverageRating"]); lblRatingStatus.Text = string.Format("{0} Users have rated. Average Rating {1}", dt.Rows[0]["RatingCount"], dt.Rows[0]["AverageRating"]); } } private DataTable GetData(string query) { DataTable dt = new DataTable(); string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString; using (SqlConnection con = new SqlConnection(constr)) { using (SqlCommand cmd = new SqlCommand(query)) { using (SqlDataAdapter sda = new SqlDataAdapter()) { cmd.CommandType = CommandType.Text; cmd.Connection = con; sda.SelectCommand = cmd; sda.Fill(dt); } } return dt; } } protected void OnRatingChanged(object sender, RatingEventArgs e) { string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString; using (SqlConnection con = new SqlConnection(constr)) { using (SqlCommand cmd = new SqlCommand("INSERT INTO UserRatings VALUES(@Rating)")) { using (SqlDataAdapter sda = new SqlDataAdapter()) { cmd.CommandType = CommandType.Text; cmd.Parameters.AddWithValue("@Rating", e.Value); cmd.Connection = con; con.Open(); cmd.ExecuteNonQuery(); con.Close(); } } } Response.Redirect(Request.Url.AbsoluteUri); } } 来允许对其存储的项目(总线)进行持续时间访问。



Set

// Helper function: given a reduced set of buses, and a count,
//   add one of those buses as the bus to take during that many stops
function addToResult(common, count, result) {
    let bus = common.values().next().value; // pick any available bus
    while (count > 0) {
        result.push(bus);
        count--;
    }
}

// Main algorithm
function getBusRide(stops) {
    if (stops.length === 0) return [];

    let result = [],
        count = 0,
        common;
    for (let buses of stops) {
        if (count == 0) { // First iteration only
            common = new Set(buses); // all buses are candidate
            count = 1;
        } else {
            let keep = new Set();
            for (let bus of buses) {
                // Only keep buses as candidate when they 
                //     are still served here
                if (common.has(bus)) keep.add(bus);
            }
            if (keep.size == 0) { // Need to change bus
                addToResult(common, count, result);
                count = 0;
                keep = new Set(buses); // all buses are candidate
            }
            common = keep;
            count++;
        }
    }
    addToResult(common, count, result);
    return result;
}

// Sample input
const stops = [
    [ 42,  45,  47],
    [ 45,  47,  42,  88],
    [ 21,  77,  42],
    [ 22,  47,  42,  88],
    [ 23,  47,  42],
    [ 24,  47,  42,  8,  91],
    [ 25,  13,  42,  3,  84],
    [ 26,  10,  11,  4,  54],
    [ 27,  9,  8,  88,   71]
];

// Apply the algorithm
console.log(getBusRide(stops));




此算法在 O(n)中运行,其中 n 是输入中值的总数,因此在示例中 n = 37