[UVa 1152] 和为0的四个值(4 Values whose Sum is 0)

xiaoxiao2021-02-28  97

Judge:https://vjudge.net/problem/UVA-1152 题意:给定4个n元素集合A,B,C,D,要求分别从中选取一个元素a,b,c,d,使得四个数之和为零。求一共有多少种选法。

n的最大值为4000,时间限制为9000ms。

很明显四重循环枚举是肯定会超时。这里采用中途相遇法,枚举所有a+b并保存起来,然后再枚举-c-d与刚才的a+b对照。

对照的方法有很多种,可以使用二分查找或哈希表。

使用二分查找:(2910ms)

#include <iostream> #include <cstring> #include <algorithm> using namespace std; long long g_arrNum[4][4010]; long long g_arrSum[4000 * 4000 + 10], g_iTop = -1; int main() { int iDataTot; cin >> iDataTot; while (iDataTot--) { memset(g_arrNum, 0, sizeof(g_arrNum)); int iNumTot, iResult = 0, g_iTop = -1; cin >> iNumTot; for (int i = 1; i <= iNumTot; i++) for (int j = 1; j <= 4; j++) cin >> g_arrNum[j - 1][i]; for (int i = 1; i <= iNumTot; i++) for (int j = 1; j <= iNumTot; j++) g_arrSum[++g_iTop] = (g_arrNum[0][i] + g_arrNum[1][j]); sort(g_arrSum, g_arrSum + g_iTop + 1); for (int i = 1; i <= iNumTot; i++) for (int j = 1; j <= iNumTot; j++) iResult += upper_bound(g_arrSum, g_arrSum + g_iTop + 1, -(g_arrNum[2][i] + g_arrNum[3][j])) - lower_bound(g_arrSum, g_arrSum + g_iTop + 1, -(g_arrNum[2][i] + g_arrNum[3][j])); cout << iResult << endl; if (iDataTot) cout << endl; } return 0; }

使用哈希表:(采用链表实现)(2300ms)

#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define HASH_MAX 23456789 struct SHashNode { long iData; int iTime; SHashNode * pNext; }; int g_arrNum[4][4010]; SHashNode g_arrHash[HASH_MAX]; void InsertHash(long iData) { int i = (iData >= 0 ? iData % HASH_MAX : iData % HASH_MAX + HASH_MAX); SHashNode * pNode = &g_arrHash[i]; while (pNode->pNext) { if (pNode->pNext->iData == iData) { pNode->pNext->iTime++; return; } pNode = pNode->pNext; } pNode->pNext = new SHashNode; pNode->pNext->iTime = 1; pNode->pNext->iData = iData; pNode->pNext->pNext = 0; } int FindHash(long iData) { int i = (iData >= 0 ? iData % HASH_MAX : iData % HASH_MAX + HASH_MAX); SHashNode * pNode = &g_arrHash[i]; while (pNode->pNext) { if (pNode->pNext->iData == iData) return pNode->pNext->iTime; pNode = pNode->pNext; } return 0; } int main() { int iDataTot; cin >> iDataTot; while (iDataTot--) { memset(g_arrNum, 0, sizeof(g_arrNum)); memset(g_arrHash, 0, sizeof(g_arrHash)); int iNumTot, iResult = 0; cin >> iNumTot; for (int i = 1; i <= iNumTot; i++) for (int j = 1; j <= 4; j++) cin >> g_arrNum[j - 1][i]; for (int i = 1; i <= iNumTot; i++) for (int j = 1; j <= iNumTot; j++) InsertHash(g_arrNum[0][i] + g_arrNum[1][j]); for (int i = 1; i <= iNumTot; i++) for (int j = 1; j <= iNumTot; j++) iResult += FindHash(-(g_arrNum[2][i] + g_arrNum[3][j])); cout << iResult << endl; if (iDataTot) cout << endl; } return 0; }在本题目使用vector实现哈希表也是可以的,但时间略长,不过也长不了多少。

转载请注明原文地址: https://www.6miu.com/read-29130.html

最新回复(0)