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

来源:互联网 发布:想搞网络课直播 编辑:程序博客网 时间:2024/06/05 16:30

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 23456789struct 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实现哈希表也是可以的,但时间略长,不过也长不了多少。

原创粉丝点击