机器人和容器最小化问题,需要采取的方法

时间:2018-12-29 12:26:11

标签: algorithm dynamic-programming greedy

给出此problem

  

您有一个仓库,其中M个容器装满了无限数量   糖果。容器均匀地排成一行   间隔为1米。您也有2个可以捡起的机器人   1块糖果,然后在任何两个容器之间运输。

     

机器人以两种形式的查询形式接受指令   整数,分别为Ma和Mb。要执行查询,机器人会前往   容器Ma,拿起1个糖果,将其运输到容器Mb,然后   停在Mb,直到收到另一个查询为止。

     

计算机器人执行必须行进的最小总距离   依次查询N个。

     

注意:您可以选择由哪个机器人执行每个查询。

最初,我认为我应该只是选择更接近执行移动操作的机器人,但是这种方法在某些测试用例中会失败,有人可以解释为什么这种方法不适用于所有情况,什么是正确的方法,谢谢。

样本输入和预期输出here

2 个答案:

答案 0 :(得分:1)

问题出在动态编程类别中,您自己标记了问题greedy(您的做法确实很贪婪)。在某些情况下,给定查询的最小距离(局部最小)对于整个查询集(全局最小)不是最佳的。因此,您需要考虑将所有可能的机器人分配给查询,但是使用DP技术并不是一个详尽的搜索。

我不想为您详细说明确切的解决方案,因为DP上有大量在线资源(制作二维成本表,跨列=机器人1,跨行=机器人2,查找通过表格的最佳路径,…)。但我想向您展示一个示例示例,其中贪婪方法不是最优的。

  • A机械手1
  • B机械手2
  • F查询的起点
  • T查询的终点

用贪婪的方法解决:

 (A)                  B
1 . . F . T . . . . . . // A is closer to F, travels 2 (to F) + 2 (to T) = 4
         (A)          B
2 . . . . . . F . T . . // A is closer to F, travels 2 (to F) + 2 (to T) = 4
                 (A)  B
3 F T . . . . . . . . . // A is closer to F, travels 8 (to F) + 1 (to T) = 9
    A                 B

总行驶距离:4 + 4 + 9 = 17

一种最佳方法(可能有多种):

 (A)                  B
1 . . F . T . . . . . . // A takes query, travels 2 (to F) + 2 (to T) = 4
          A          (B)
2 . . . . . . F . T . . // B takes query, travels 4 (to F) + 2 (to T) = 6
         (A)      B
3 F T . . . . . . . . . // A takes query, travels 4 (to F) + 1 (to T) = 5
    A             B

总行驶距离:4 + 6 + 5 = 15

请注意,B进行了第二次查询,即使它离起点的距离最近。

答案 1 :(得分:0)

在C ++中使用动态编程的工作代码(如AurelBílý所述):

#include <bits/stdc++.h>
using namespace std;
vector <pair <int,int > > input;
int dp[1002][1002];
int m,n;
int dis(int a,int b)
{
    if(a == 0) return abs(input[b-1].first-input[b-1].second);
    return abs(input[a-1].second-input[b-1].first)+abs(input[b-1].first-input[b-1].second);
}
int func(int i,int j)
{
    if(i+1 == n+1 || j+1 == n+1)
    {
        return 0;
    }
    //cout<<i<<" "<<j<<endl;
    if(dp[i][j] != -1)
     return dp[i][j];
    int result = INT_MAX;
    result = min(func(i,j+1)+dis(j,j+1),func(j,j+1)+dis(i,j+1));
    return dp[i][j] = result; 
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>m>>n;
        input.clear();
        input.resize(n);
        for(int i=0;i<n;i++)
        {
            int a,b;
            cin>>a>>b;
            input[i] = make_pair(a,b);
        }
        memset(dp,-1,sizeof(dp));
        int first = abs(input[0].first-input[0].second);
       // int second = abs(input[1].first-input[1].second);
        int val = func(0,1)+first;
        cout<<val<<endl;
    }
    return 0;
}