【问题标题】:Google Code Jam Minimum Scalar ProductGoogle Code Jam 最小标量积
【发布时间】:2016-05-08 21:17:53
【问题描述】:

我正在通过 Google Code Jam 解决一个问题,但我无法解决该问题:http://code.google.com/codejam/contest/32016/dashboard#s=p0(最小标量积,问题 A 2008)

我使用的策略是:

  1. 接受用户的v1v2
  2. v1v2 进行排序
  3. 反转v2,即按降序对v2进行排序
  4. 将对应的v1[i] * v2[i]直接相乘并将结果存储在product
  5. 总结所有此类产品并打印答案

我做了一些研究,确实这似乎是唯一可能获得的排列。但是,我的代码没有产生正确的输出:

#include <stdio.h>
#include <algorithm>
#include <iostream>

using namespace std;
int main()
{

    int T;
    int cases;
    FILE *fin  = fopen ("A-small-practice.in", "r"); // open input file
    FILE *fout = fopen ("output.out", "w");

    fscanf(fin, "%d", &T);
    for(cases = 1; cases <= T; cases++)
    {
        int v1[1000], v2[1000];
        int i,j; int n;
        int product =0;
        fscanf(fin, "%d", &n);

        for(i=0; i < n; i++)
        {            
            fscanf(fin, "%d",&v1[i]);
            fscanf(fin, "%d", &v2[i]);            
        }

        sort(v1,v1+n);
        sort(v2,v2+n);
        reverse(v1, v1+n);

        int k;
        for(k = 0; k < n; k++)
        {                        
            product += v1[k] * v2[k];            
        }
        fprintf(fout, "Case #%d: %d\n", cases, product);
    }
    return 0;    
}

【问题讨论】:

    标签: c++ algorithm


    【解决方案1】:

    您应该使用long long。 这对我有用:

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int main() {
    long long T,n,v1[1000],v2[1000];
    cin >> T;
    for (int t = 1; t <= T; t++) {
        cin >> n;
        for (int i = 0; i < n; i++)
            cin >> v1[i];
        for (int i = 0; i < n; i++)
            cin >> v2[i];
        sort(v1,v1+n);
        sort(v2,v2+n);
        long long p = 0;
        for (int i = 0; i < n; i++)
            p += v1[i]*v2[n-i-1];
        cout << "Case #" << t << ": " << p << endl;
    }
    return 0;
    }
    

    【讨论】:

      【解决方案2】:

      经过数小时的故障排除后,我发现问题出在输入的方式上,因为我对 v1 和 v2 都只使用了一个循环:

      for(i=0; i < n; i++)
          {            
              fscanf(fin, "%d",&v1[i]);
              fscanf(fin, "%d", &v2[i]);            
          }
      

      应该是这样的:

      for(i=0; i<n; i++)
      fscanf(fin, "%d",&v1[i]);
      for(i=0; i<n; i++)
      fscanf(fin, "%d", &v2[i]);
      

      谢谢 lukas1994 和 pkacprzak

      【讨论】:

        【解决方案3】:

        这对我有用:

        #include <algorithm>
        #include <iostream>
        #include <vector>
        #include <numeric>
        
        using std::vector;
        
        long long min_dot_product(size_t n, vector<int> a, vector<int> b) {
            long long result = 0;
            if (n != 0)
            {
                std::sort(a.begin(), a.end());
                std::sort(b.begin(), b.end());
                std::reverse(a.begin(), a.end());
        
                /*for (size_t i = 0; i < n; i++) {
                    result += a[i] * b[n - 1 - i];
                }*/
        
                result = std::inner_product(a.begin(), a.end(), b.begin(), 0);
        
            }
            return result;
        }
        
        int main() {
            size_t n;
            std::cin >> n;
            vector<int> a(n), b(n);
            for (size_t i = 0; i < n; i++) {
                std::cin >> a[i];
            }
            for (size_t i = 0; i < n; i++) {
                std::cin >> b[i];
            }
            std::cout << min_dot_product(n, a, b) << std::endl;
        }
        

        【讨论】:

          【解决方案4】:

          有具体情况需要考虑。

          当一个向量全为负而另一个全为正时,算法不会产生最小结果。

          if x = [-1,-2] and x = [1,2]
          

          根据算法输出的最小值是:

          (-1*2) + (-2*1) = -4
          

          但是,如果您在这种情况下使用 x1y1 + x2y2... xnyn,您会得到:

          (-1 * 1) + ( -2*2) = -1-4 = -5
          

          【讨论】:

          • 这不是一个真正的答案,而是一个评论(虽然我理解使用答案框是可读的)。但是,即使这样接受它,也不清楚您正在评论哪个答案,或者您将如何改进它。
          • @snoeyink 这个答案是错误的,算法确实给出了正确的答案,在你的例子中,你对 -ve 数字进行了错误的排序。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-10
          • 1970-01-01
          相关资源
          最近更新 更多