日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POJ 2785 有多少种4个数相加等于0的方案(二分查找 or hash)

發布時間:2024/7/5 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 2785 有多少种4个数相加等于0的方案(二分查找 or hash) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1.二分查找法
      • 1.1 思路:
      • 1.2 AC代碼
    • 2.hash查找法
      • 2.1 思路:
      • 2.2 Wrong Answer 代碼
      • 2.3 Time Limit Exceeded 代碼
      • 2.4 偷懶失敗,hash_map在poj中不存在
      • 2.5 哈希表+二叉查找樹(超時)
      • 2.6 AC代碼(哈希+數組法)

題目鏈接: http://poj.org/problem?id=2785

題目大意:給定不超過4000行4個數,每列挑出來1個,使之和為0,有多少種方案。

1.二分查找法

1.1 思路:

  • 對左邊兩列的所有和求出來,右邊兩列所有的和的求出來再取負
  • 右側兩列的值排序(進行二分查找)
  • 對左邊所有的和在右邊的和中進行二分查找,并查找前后都滿足要求的,計數即得答案

1.2 AC代碼

/*** @description: 求四個數相加等于0的組合種數* @author: michael ming* @date: 2019/5/8 22:18* @modified by:*/ #include <iostream> #include <memory.h> #include <algorithm>using namespace std; int a[4001], b[4001], c[4001], d[4001]; int ab[4000*4000+1], cd[4000*4000+1]; //存儲a+b,c+d int findSameValue(int value, int maxindex)//二分查找 {int low = 0, high = maxindex, mid, index, count=0;while(low <= high){mid = low + (high - low)/2;if(value == cd[mid]) //查找前后滿足要求的個數{index = mid - 1;while(index >= 0 && value == cd[index--])count++;index = mid + 1;while(index <= high && value == cd[index++])count++;return count + 1;}else if(value < cd[mid])high = mid - 1;elselow = mid + 1;}return 0; } int main() {int line, k=0;cin >> line;memset(ab, 0, sizeof(ab));memset(cd, 0, sizeof(cd));for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];cd[k++] = -(c[i]+d[j]);}}sort(cd,cd+k); //二分查找的必要條件,有序int result = 0;for(int i = 0; i <= k-1; ++i)result += findSameValue(ab[i], k-1);cout << result << endl;return 0; }

2.hash查找法

2.1 思路:

  • 對左邊兩列的所有和求出來,右邊兩列所有的和的求出來再取負
  • 對左側兩列的和存入哈希表
  • 對右邊兩列的和在哈希表中查找

2.2 Wrong Answer 代碼

(未解決沖突,并且hash后的值可能為負,作為數組下標不行,所以錯誤)

/*** @description: 4個數和為0的方案數,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by: */ #include <iostream> #include <memory.h> using namespace std; int a[4001], b[4001], c[4001], d[4001]; int ab[4000*4000+1], cd[4000*4000+1]; //存儲a+b,c+d int *hasht = new int[16000057]; int offset = 1000000000; int hashfunc(int &value) {int mod = 16000057;return (value%mod + value/mod)%mod; } int main() {int line, k=0, value;cin >> line;memset(hasht, 0, sizeof(hasht));for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];value = ab[k]+offset;hasht[hashfunc(value)]++;cd[k++] = -(c[i]+d[j]);}}int result = 0;for(int i = 0; i < k; ++i){value = cd[i]+offset;if(hasht[hashfunc(value)])result += hasht[hashfunc(value)];}cout << result << endl;delete [] hasht;return 0; }

2.3 Time Limit Exceeded 代碼

/*** @description: 4個數和為0的方案數,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by: */ #include <iostream> #include <math.h> using namespace std; struct linkedNode //鏈表節點 {pair<int, int> data;linkedNode *next;linkedNode():next(NULL), data(make_pair(0,0)){} }; class linkedList //鏈表 { public:linkedNode *head;linkedList(){head = new linkedNode(); //表頭哨兵}~linkedList(){delete head;} }; class linkedHash { private:linkedList *htList; //散列表鏈表數組int bucket; //散列表桶個數 public:linkedHash(int m):bucket(m){htList = new linkedList [bucket] ();}~linkedHash(){for(int i = 0; i < bucket; ++i){linkedNode *p = htList[i].head->next, *q = p;while(q != NULL){p = q;q = q->next;delete p;}}delete [] htList;}int hash(const int &key) const{return abs(key%bucket); //留余數法}linkedNode* find(const int &x) const{int i = hash(x);linkedNode *p = htList[i].head->next, *q = htList[i].head;while(p && p->data.first != x){q = p;p = p->next;}return q; //返回找到元素的前一個節點,或者沒有找到,返回最后一個元素}linkedNode* insert(const int &x){int i = hash(x);linkedNode *p = htList[i].head, *q = p;while(q != NULL){p = q;q = q->next;if(q && q->data.first == x){q->data.second++;return q;}}p->next = new linkedNode();p->next->data.first = x;p->next->data.second++;return p->next;} }; int a[4001], b[4001], c[4001], d[4001]; int ab[4000*4000+1], cd[4000*4000+1]; //存儲a+b,c+d int main() {linkedHash ht(16000057);int line, k=0;cin >> line;for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];ht.insert(ab[k]);cd[k++] = -(c[i]+d[j]);}}int result = 0;linkedNode* p;for(int i = 0; i < k; ++i){p = ht.find(cd[i])->next;if(p && p->data.first == cd[i])result += p->data.second;}cout << result << endl;return 0; }

2.4 偷懶失敗,hash_map在poj中不存在

/*** @description: 4個數和為0的方案數,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by: */ #include <iostream> #include <hash_map> //#include <unordered_map> using namespace std; int a[4001], b[4001], c[4001], d[4001]; int ab[4000*4000+1], cd[4000*4000+1]; //存儲a+b,c+d int main() {__gnu_cxx::hash_map<int, int> ht; // std::unordered_map<int, int> ht;int line, k=0;cin >> line;for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];ht[ab[k]]++;cd[k++] = -(c[i]+d[j]);}}int result = 0;for(int i = 0; i < k; ++i){result += ht[cd[i]];}cout << result << endl;return 0; }

2.5 哈希表+二叉查找樹(超時)

可能是建立二叉樹插入節點new太耗時了。

/*** @description: 4個數和為0的方案數,哈希法* @author: michael ming* @date: 2019/5/9 22:30* @modified by:*/ #include <iostream> #include <math.h> using namespace std; class BSTNode { public:int data, count;BSTNode *left, *right;BSTNode():count(1), left(NULL), right(NULL){}BSTNode(const int& d, BSTNode *l = NULL, BSTNode *r = NULL){data = d; count = 1; left = l; right = r;} }; class BST { private:BSTNode* root;int nodeLen; public:BST():root(NULL){}~BST(){}void clear(BSTNode* nodeP){if(nodeP == NULL)return;clear(nodeP->left);clear(nodeP->right);delete nodeP;}BSTNode* get_root() const { return root; }bool isEmpty() const { return root == NULL; }BSTNode* search(const int& d) const{BSTNode* p = search(d, root);return p;}BSTNode* search(const int d, BSTNode* p) const{while(p != NULL){if(d == p->data)return p;else if(d < p->data)p = p->left;elsep = p->right;}return NULL;}void insert(const int d){BSTNode *p = root, *prev = NULL;while(p != NULL){prev = p;if(d < p->data)p = p->left;elsep = p->right;}if(root == NULL)root = new BSTNode(d);else if(d < prev->data)prev->left = new BSTNode(d);elseprev->right = new BSTNode(d);} };class linkedHash { private:BST* ht_bstree; //散列表二叉樹數組int bucket; //散列表桶個數 public:linkedHash(int m):bucket(m){ht_bstree = new BST [bucket] ();}~linkedHash(){for(int i = 0; i < bucket; ++i){ht_bstree[i].clear(ht_bstree[i].get_root());}delete [] ht_bstree;}int hash(const int &key) const{return abs((((key+1000000000)%bucket)+1357)%bucket); //留余數法}int find(const int &x) const{int i = hash(x);BSTNode *p = ht_bstree[i].search(x);if(p)return p->count;return 0;}void insert(const int x){int i = hash(x);BSTNode *p = ht_bstree[i].search(x);if(p)p->count++;elseht_bstree[i].insert(x);} }; int a[4001], b[4001], c[4001], d[4001]; int ab[4000*4000+1], cd[4000*4000+1]; //存儲a+b,c+d int main() {linkedHash ht(5000); //多次調整括號內數值,超時或者內存超限int line, k=0;cin >> line;for(int i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(int i = 0; i < line; ++i){for(int j = 0; j < line; ++j){ab[k] = a[i]+b[j];ht.insert(ab[k]);cd[k++] = -(c[i]+d[j]);}}int result = 0;for(int i = 0; i < k; ++i){result += ht.find(cd[i]);}cout << result << endl;return 0; }

2.6 AC代碼(哈希+數組法)

/*** @description: poj 2785 哈希法,數組實現* @author: michael ming* @date: 2019/5/20 18:17* @modified by: */ #include <iostream> using namespace std; int a[4001], b[4001], c[4001], d[4001]; const int hashtablesize = 20000001;//保證一定的富裕,裝載因子0.75左右 int hasht[hashtablesize]; int count[hashtablesize]; int offset = 1000000000; // 該數 > 2^29(加上他后,就沒有負數了,求模后比較方便使用下標值) int hashfunc(int value) {return value%hashtablesize; } int hashfunc_other(int value) {return (value+3)%hashtablesize; } void insert(int num) {int num_init = num;num = hashfunc(num+offset);while(hasht[num] != offset && hasht[num] != num_init)//解決沖突,不等于初始值(夠不著的大數)(值改了,位子被占了),且不等于映射的值(沖突了),第一次進入循環,第一個條件肯定不滿足。{num = hashfunc_other(num);//沖突了,繼續尋找別的下標(換一個函數,不然相同的模在這可能無限循環)}hasht[num] = num_init;count[num]++; } int find(int num) {int num_init = num;num = hashfunc(num+offset);while(hasht[num] != offset && hasht[num] != num_init)num = hashfunc_other(num); //往下查找空位或者相等的值得位子if(hasht[num] == offset) //找到的是空位子,則沒有匹配的和等于0return 0;else //找到了值相等的位子,把其對應的count位子里的個數返回return count[num]; } int main() {int line, k=0, value, i, j;cin >> line;for(i = 0; i < line; ++i){cin >> a[i] >> b[i] >> c[i] >> d[i];}for(i = 0; i < hashtablesize; ++i)hasht[i] = offset; //hash表每個元素初始化為offsetfor(i = 0; i < line; ++i){for(j = 0; j < line; ++j){value = a[i]+b[j];insert(value);}}int result = 0;for(i = 0; i < line; ++i){for(j = 0; j < line; ++j){value = (-c[i]-d[j]);result += find(value);}}cout << result << endl;return 0; }

總結

以上是生活随笔為你收集整理的POJ 2785 有多少种4个数相加等于0的方案(二分查找 or hash)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。