【问题标题】:How to solve BAISED on SPOJ?如何解决 SPOJ 上的 BAISED?
【发布时间】:2016-02-11 16:54:24
【问题描述】:

我正在尝试解决这个 SPOJ 问题http://www.spoj.com/problems/BAISED/

我的方法

for all elements in the preferred_position array
 if(position>0&&position<=n)
    if(position is unoccupied)
       allocate position for user
 else
   reach the first free position in the array

for all elements whose preferred position is already filled
    search both directions left,right to find nearest free_position

我尝试了许多测试用例,并得到了正确的结果,但我不知道我在哪里失败并得到了错误的答案。我根据贪婪标签选择了这个问题,我真的不知道在哪里应用贪婪技术。谁能给点灯?

【问题讨论】:

    标签: algorithm greedy


    【解决方案1】:

    这是我接受的解决方案!

    我发送了几次,直到意识到数字可能非常大,所以我将所有内容都更改为 long long

    只需对数字进行排序,然后找出它们的位置之间的差异。

    我是如何找到这个解决方案的:

    1) 您应该将所有团队放在从 0 到 n - 1 的位置

    2) 让尽可能多的团队在他们喜欢的地方放置

    3) 其余未上位的球队与上位的球队拥有相同的首选位置 团队或首选位置很大,然后 n - 1(或 n - 如果 枚举自 1)

    4) 我们记得我们需要将所有位置从 0 下降到 n - 1, 所以很明显,如果我们对未放置的团队进行排序,我们可以最小化 答案

    为什么我跳过第二步(你可以尝试证明它),让我们看看示例测试:

    1
    3
    first team 2
    second team 3
    third team 4
    4 2 3 -> |1 - 4| + |2 - 2| + |3 - 3| = 3
    2 3 4 -> |1 - 2| + |2 - 3| + |3 - 4| = 3
    
        #include <iostream>
        #include <vector>
        #include <algorithm>
    
        using namespace std;
        int main() {
            ios::sync_with_stdio(false);
            long long t;
            cin >> t;
            vector <long long> a;
            for (long long i = 0; i < t; i++) {
               long long n;
               cin >> n;
                a.clear();
                for (long long j = 0; j < n; j++) {
                    string s;
                    cin >> s;
                    long long p ;
                    cin >> p;
                    p--;
                    a.push_back(p);
                }
                sort(a.begin(), a.end());
                long long ans = 0;
                for (long long i = 0; i < a.size(); i++) {
    
                    ans += abs(a[i] - i);
                }
                cout << ans << '\n';
           }
        }
    

    【讨论】:

    • 谢谢!我不明白这如何导致最佳解决方案,因为 position_preferred 和 position_allotted 的变化可能会导致连续元素的变化。我首先定位了首选位置在范围内的元素,如果该位置为空。后来,我左右遍历,以获得首选位置已被占用的元素的最近位置。我会错在哪里?这是代码ideone.com/O4ood1的链接
    • @user 我知道您的解决方案将落在哪个测试用例上。我会尝试形式化和解释。
    【解决方案2】:

    我会错在哪里?这是代码ideone.com/O4ood1的链接

    阅读您的代码非常痛苦..您的解决方案不是 100% 正确的,因为:

    1. 可能有大于 10^10 的非常大的数字,你做错了什么 - 它会将这个数字减一,直到你达到 n,你的生命太短了,等待你的解决方案找到结果对于这么大的数字进行测试...如果你想让 a[i] 小于或等于 n,为什么不写 a[i] = n)

      while(t2>n)
          {
              t2--;
              cnt1++;
          }
      
    2. 我在同一个测试用例上运行了您的代码两次,但在第二次 运行我在测试中更改给定数字的顺序,您的解决方案显示 不同的答案:

      我删除了读取字符串以便于调试。所以我提供了没有团队名称的测试

      首次运行测试:

      1

      10

      2 3 4 5 6 7 8 9 7 6

      您的解决方案显示结果为 6出了什么问题 回答

      第二次运行:让我们改变交换最后两个数字并得到

      2 3 4 5 6 7 8 9 6 7

      您的解决方案显示答案是 8(幸运的是 正确答案)

    3. 假设有两个未放置的数字 a[6] = 6a[9] = 9 , 和 有两个空位1和8

      您的解决方案将采取 6 向右走 步,并将 6 置于位置 8,然后将拿 9 并放在位置 1

      如果您从号码的开始位置到其 destination 你会看到从 91 的那条线完全覆盖 6 的那条线到 8... 看起来不是最佳的。

      所以你应该尽量避免这种重叠

      现在画线从6到1和从9到8,没有 重叠,现在它是最佳的。

      So to avoid overlapping   you can for example to sort rest of your numbers.
      

    【讨论】:

    • 非常感谢@d40a 并为错误且难以理解的代码感到抱歉
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    相关资源
    最近更新 更多