Google code jam: Problem A. Minimum Scalar Product

Problem

You are given two vectors v1=(x1,x2,...,xn) and v2=(y1,y2,...,yn). The scalar product of these vectors is a single number, calculated as x1y1+x2y2+...+xnyn.

Suppose you are allowed to permute the coordinates of each vector as you wish. Choose two permutations such that the scalar product of your two new vectors is the smallest possible, and output that minimum scalar product.

Input

The first line of the input file contains integer number  T  - the number of test cases. For each test case, the first line contains integer number  n . The next two lines contain  n integers each, giving the coordinates of v 1  and v 2  respectively.

Output

For each test case, output a line

Case #X: Y
where  X  is the test case number, starting from 1, and  Y  is the minimum scalar product of all permutations of the two given vectors.

Limits

Small dataset

T = 1000
1 ≤ n ≤ 8
-1000 ≤ xiyi ≤ 1000

Large dataset

T = 10
100 ≤ n ≤ 800
-100000 ≤ xiyi ≤ 100000

Sample


Input 
 

Output 
 
2
3
1 3 -5
-2 4 1
5
1 2 3 4 5
1 0 1 0 1

Case #1: -25
Case #2: 6


我的代码:


#include <iostream>
#include <cstdio>

using namespace std;

#define LARGE

void bubble_sort(__int64* &array,int size);
int main()
{
#ifdef SMALL
	freopen("a_small.in","r",stdin);
	freopen("a_samll.out","w",stdout);
#endif

#ifdef LARGE  //
	freopen("a_large.in","r",stdin);
	freopen("a_large.out","w",stdout);
#endif
	
	__int64 * v1;
	__int64 * v2; //No.2
	int T,N;
	__int64 Y;
	cin>>T;
	for(int i=0;i!=T;++i)
	{
		cin>>N;
		v1 = new __int64[N];
		v2 = new __int64[N];
		Y=0;
		for(int j=0;j!=N;++j)
			scanf("%I64d",&v1[j]);
		for(j=0;j!=N;++j)
			scanf("%I64d",&v2[j]);
		bubble_sort(v1,N);//No.1
		bubble_sort(v2,N);
		for(j=0;j!=N;++j)
		{
			Y+=v1[j]*v2[N-1-j];
		}
		cout<<"Case #"<<i+1<<": ";
		printf("%I64d\n",Y);

	}
	return 0;
}
void bubble_sort(__int64* &array,int size) //No.3
{
	int temp;
	for(int i=0;i!=size-1;++i)
	{
		for(int j=i+1;j!=size;++j)
		{
			if(array[j]>array[i])
			{
				temp=array[i];
				array[i]=array[j];
				array[j]=temp;
			}
		}
	}
}

思路:

此题说的是,给两个整型数组,要求出这个数组内积的最小值,这个数组内积在题中有定义。此题思路很简单,先对这两个数组进行排序,然后用数组1的最小值乘以数组2的最大值,然后加上数组1的次小值乘以数组2的次大值,依此类推,得到的最终值就是那个内积的最小值。对于此题有两点可以注意下:

No.1 & No.3: 第一点是这个排序算法没有问题,而且在数组指针以引用的形式传递指针的时候,注意写法。这样就可以直接返回对数组的操作。比如int数组,就是写成int* &a.加入int* a是指向此数组的指针。所以可以读成指向a数组指针的引用。这是一点。但是关于排序这里我最想说的是:其实在C++标准库里面有很好的排序函数,在<algorithm>头文件下,sort()函数,具体用法请baidu‘之。那样的话,可以使代码更简洁,对于程序员来讲,可以专注于问题和算法。

No.2: 第二点是此题的小数据其实问题不大,思路很简单,它的乘积不会超过int的表示范围。下面我把数据类型的表示范围贴出来。

For 32-bit and 64-bit compilers, Microsoft Visual C++ recognizes the types shown in the table below. Note that the following type also have unsigned forms:

Type Name Bytes Other Names Range of Values

int

4

signed

–2,147,483,648 to 2,147,483,647

unsigned int

4

unsigned

0 to 4,294,967,295

__int8

1

char

–128 to 127

unsigned __int8

1

unsigned char

0 to 255

__int16

2

short, short int, signed short int

–32,768 to 32,767

unsigned __int16

2

unsigned short, unsigned short int

0 to 65,535

__int32

4

signed, signed int, int

–2,147,483,648 to 2,147,483,647

unsigned __int32

4

unsigned, unsigned int

0 to 4,294,967,295

__int64

8

long long, signed long long

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

unsigned __int64

8

unsigned long long

0 to 18,446,744,073,709,551,615

bool

1

none

false or true

char

1

none

–128 to 127 by default

0 to 255 when compiled with /J

signed char

1

none

–128 to 127

unsigned char

1

none

0 to 255

short

2

short int, signed short int

–32,768 to 32,767

unsigned short

2

unsigned short int

0 to 65,535

long

4

long int, signed long int

–2,147,483,648 to 2,147,483,647

unsigned long

4

unsigned long int

0 to 4,294,967,295

long long

8

none (but equivalent to __int64)

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

unsigned long long

8

none (but equivalent to unsigned __int64)

0 to 18,446,744,073,709,551,615

enum

varies

none

See Remarks.

float

4

none

3.4E +/- 38 (7 digits)

double

8

none

1.7E +/- 308 (15 digits)

long double

same as double

none

same as double

wchar_t

2

__wchar_t

0 to 65,535

可以看到在32bit机器上,int类型和long类型都是表示一样的数据范围,在10位整数。小数据没有问题,但是大数据有问题,你看大数据的范围。它的最大可能乘积到了11位了,所以要用到long long类型或者叫做__int64,它能表示19位整数。符合我们题目要求。

具体在各种不同的编译器下面使用这种长整数类型,请看下表:

zz from http://www.byvoid.com/blog/c-int64/

在C/C++中,64为整型一直是一种没有确定规范的数据类型。现今主流的编译器中,对64为整型的支持也是标准不一,形态各异。一般来说,64位整型的定义方式有long long和__int64两种(VC还支持_int64),而输出到标准输出方式有printf(“%lld”,a),printf(“%I64d”,a),和cout << a三种方式。

本文讨论的是五种常用的C/C++编译器对64位整型的支持,这五种编译器分别是gcc(mingw32),g++(mingw32),gcc(linux i386),g++(linux i386),Microsoft Visual C++ 6.0。可惜的是,没有一种定义和输出方式组合,同时兼容这五种编译器。为彻底弄清不同编译器对64位整型,我写了程序对它们进行了评测,结果如下表。


变量定义 输出方式 gcc(mingw32) g++(mingw32) gcc(linux i386) g++(linux i386) MicrosoftVisual C++ 6.0
long long “%lld” 错误 错误 正确 正确 无法编译
long long “%I64d” 正确 正确 错误 错误 无法编译
__int64 “lld” 错误 错误 无法编译 无法编译 错误
__int64 “%I64d” 正确 正确 无法编译 无法编译 正确
long long cout 非C++ 正确 非C++ 正确 无法编译
__int64 cout 非C++ 正确 非C++ 无法编译 无法编译
long long printint64() 正确 正确 正确 正确 无法编译

 

上表中,正确指编译通过,运行完全正确;错误指编译虽然通过,但运行结果有误;无法编译指编译器根本不能编译完成。观察上表,我们可以发现以下几点:

  1. long long定义方式可以用于gcc/g++,不受平台限制,但不能用于VC6.0。
  2. __int64是Win32平台编译器64位长整型的定义方式,不能用于Linux。
  3. “%lld”用于Linux i386平台编译器,”%I64d”用于Win32平台编译器。
  4. cout只能用于C++编译,在VC6.0中,cout不支持64位长整型。

zz from http://blog.csdn.net/zhlynn/archive/2009/03/28/4032152.aspx

64位整数全解(增补板) 
  
64位整形引起的混乱主要在两方面,一是数据类型的声明,二是输入输出。

首先是如果我们在自己机器上写程序的话,情况分类如下:

(1) 在win下的VC6.0里面,声明数据类型的时候应该写作

__int64 a;

输入输出的时候用 %I64d

scanf(”%I64d”,&a);
printf(”%I64d”,a);

(2) 在linux下的gcc/g++里面,数据类型声明写作

long long a;

输入输出时候用 %lld

(3) 在win下的其它IDE里面[包括高版本Visual Studio],数据类型声明用上面两种均可

输入输出用 %I64d


注意上面红色粗体,那个64前面是大写的I,不是小写的l。至于为什么不是long的首字母,而是大写的I,我也是试过出了错才知道的。


使用C++标准库定义的模板类vector和函数来解决

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main()
{
	freopen("a_large.in","r",stdin);
	freopen("a_large.out","w",stdout);
	int T,n;
	__int64 temp,Y;
	cin>>T;
	for(int i=0;i!=T;++i)
	{
		cin>>n;
		vector<__int64> v1,v2;
		for(int j=0;j!=n;++j)
		{
			scanf("%I64d",&temp);
			v1.push_back(temp);
		}
		for(j=0;j!=n;++j)
		{
			scanf("%I64d",&temp);
			v2.push_back(temp);
		}
		sort(v1.begin(),v1.end());
		sort(v2.begin(),v2.end());
		Y=0;
		for(j=0;j!=n;++j)
		{
			Y+=v1[j]*v2[n-j-1];
		}
		cout<<"Case #"<< (i+1) <<": ";
		printf("%I64d\n",Y);
	}

	return 0;
}


你可能感兴趣的:(Google code jam: Problem A. Minimum Scalar Product)