Google Code Jam最小标量积

时间:2014-04-09 20:54:33

标签: c++ algorithm

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

我使用的策略是:

  1. 从用户
  2. 接受v1v2
  3. v1v2
  4. 进行排序
  5. 反向v2,即按降序排序v2
  6. 将相应的v1[i] * v2[i]直接相乘并将结果存储在product
  7. 总结所有此类产品并打印答案
  8. 我做了一些研究,实际上它似乎是唯一可以获得的排列。但是,我的代码没有产生正确的输出:

    #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;    
    }
    

4 个答案:

答案 0 :(得分:2)

您应该使用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;
}

答案 1 :(得分:0)

经过几个小时的故障排除后,我发现问题出在输入方式上,因为我只使用了一个循环用于v1和amp; 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

答案 2 :(得分:0)

这对我有用:

#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;
}

答案 3 :(得分:-1)

有一个具体案例需要考虑。

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

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

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

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

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

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