1. 程式人生 > >UVa 1592 Database (map)

UVa 1592 Database (map)

tid one 做到 bre 復雜度 font 16px tmp put

題意:給出n行m列的數據庫(數據範圍: n 1~10000, m 1~10), 問你能不能找出兩行r1, r2,使得這兩行中的c1, c2列是一樣的, 即(r1,c1)==(r2,c1) && (r1,c2)==(r2,c2), 可以的話輸出NO並且輸出r1, r2, c1, c2, 否則輸出YES!

分析:如果是四個for循環去枚舉全部的r1,r2,c1,c2復雜度是O(n*n*m*m),肯定超時!能否減少枚舉量?或者只是枚舉行或者列?這裏可以使用map做到!map的鍵值設置為一個pair<int, int>存儲每一行c1,c2, 第二個值設置為此二元組所在的行, 即map<pair<int,int>,int> == map( <c1, c2>, row ), 這樣只要枚舉每一行的二元組,然後一行行枚舉下去,如果有重復出現的,比如這時候枚舉到第i行,然後有其中一個二元組(c1, c2)重復出現,那map[make_pair(c1, c2)]就是之前第一次出現此二元組的行數,第二次出現的行數便是i了!其中可以使用map當類似哈希效果的作用,即將string轉化成int,提取字符串也可以用到stringstream類來進行,什麽?本身就有空格?將其填充為一個不可能的字符呀,然後將‘,‘變成‘ ‘就OK了!

瞎想:為什麽不用set?因為不能知道第一次出現二元組的行數呀!

能不能行列顛倒來枚舉?不可以!

技術分享
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<set>
#include<map>
#include<sstream>
#include<math.h>
using namespace std;
map
<pair<int, int>, int> sqare; map<string, int> M; int G[10001][11]; int num = 0; int Getid(string s) { if(M.count(s)) return M[s]; return M[s] = num++; } int main(void) { int n, m; while(scanf("%d%d", &n, &m)==2){ getchar(); M.clear(); num
= 0; sqare.clear(); int j = 0; for(int i=0;i<n;i++){ j = 0; string tmp; getline(cin, tmp); for(int k=0; k<tmp.length(); k++){ if(tmp[k]==,) tmp[k] = ; else if(tmp[k]== ) tmp[k] = }; } stringstream s; s<<tmp; string temp; while(s>>temp){ G[i][j++] = Getid(temp); } } // for(int ii=0; ii<n; ii++){ // for(int jj=0; jj<m; jj++){ // printf("%d ", G[ii][jj]); // } // puts(""); // } int index = -1, i, k; for(j=0; j<m-1; j++){//註意枚舉的順序!我一開始就蓋了個0~n的傻逼循環 for(k=j+1; k<m; k++){ sqare.clear();//註意clear(),因為這個位置的二元組已經枚舉完了,沒有 我們想要的! for(i=0; i<n; i++){ if(sqare.count(make_pair(G[i][j], G[i][k]))){ index = sqare[make_pair(G[i][j], G[i][k])]; break; } sqare[make_pair(G[i][j], G[i][k])] = i; } if(index!=-1) break; } if(index!=-1) break; } if(index==-1) puts("YES"); else{ puts("NO"); printf("%d %d\n", index+1, i+1); printf("%d %d\n", j+1, k+1); } } return 0; }
View Code

UVa 1592 Database (map)