1.暴力求解法 (DFS)html
對於每一時刻的局面,能夠抽象成一個圖。問題就是分別求每一時刻圖中連通份量的個數。如何求圖的連通份量的個數呢?能夠使用深度優先搜索DFS。假設圖中節點數爲N*M,那麼每一時刻都須要遍歷N*M節點來求取連通份量個數。一樣,咱們有N*M個時刻。最終的算法複雜度爲O( (N*M)2 )。ios
2.並查集算法
咱們先來看一看何爲並查集,這裏我再也不贅述,分享一篇好文章,那麼如何利用並查集優化問題求解呢,思路來自於這裏。優化
1 #include <iostream> 2 3 using namespace std; 4 5 const int MAXSIZE = 1000*1000+1; 6 int uset[MAXSIZE]; 7 int answer[MAXSIZE]; 8 pair<short,short> valueToIndex[MAXSIZE]; 9 const int dx[]={-1,0,0,1},dy[]={0,-1,1,0}; 10 11 //void makeSet(int size) { 12 // for(int i = 1;i <= size;i++) uset[i] = -MAXSIZE; 13 //} 14 15 int find(int x) { 16 int p = x, t; 17 while (uset[p] > 0) p = uset[p]; 18 while (x != p ) { 19 t = uset[x]; 20 uset[x] = p; 21 x = t; 22 } 23 return x; 24 } 25 26 void unionSet(int x, int y) { 27 if ((x = find(x)) == (y = find(y))) return; 28 if (uset[x] < uset[y]) { 29 uset[x] += uset[y]; 30 uset[y] = x; 31 } else { 32 uset[y] += uset[x]; 33 uset[x] = y; 34 } 35 } 36 37 void unionSetRoot(int x,int y) 38 { 39 if (uset[x] < uset[y]) { 40 uset[x] += uset[y]; 41 uset[y] = x; 42 } else { 43 uset[y] += uset[x]; 44 uset[x] = y; 45 } 46 } 47 48 int raw,col; 49 int main() 50 { 51 52 scanf("%d%d",&raw,&col); 53 int size = raw * col; 54 //makeSet(size); 55 56 for(short i=1;i<=raw;i++) 57 for(short j=1;j<=col;j++) 58 { 59 int value; 60 scanf("%d",&value); 61 valueToIndex[value] = make_pair(i,j); 62 } 63 64 for(int evaWater=size-1;evaWater>=1;evaWater--) 65 { 66 int lastEvaWater = evaWater+1; 67 int x = valueToIndex[lastEvaWater].first; 68 int y = valueToIndex[lastEvaWater].second; 69 int lastValueIndex = (x-1)*col +y; 70 uset[lastValueIndex] = -1; 71 answer[evaWater] = answer[lastEvaWater]+1; 72 73 for(int dir=0;dir<4;dir++) 74 { 75 int tx=x+dx[dir],ty=y+dy[dir]; 76 77 if(tx >=1&& tx <=raw && ty>=1 && ty<= col ) 78 { 79 int los =(tx-1)*col+ty; 80 81 if( uset[los] !=0 ) 82 { 83 int key = find(los); 84 int last = find(lastValueIndex); 85 if(last != key) 86 { 87 unionSetRoot(last,key); 88 answer[evaWater]--; 89 } 90 91 } 92 93 } 94 } 95 96 97 } 98 99 100 for (int i=1;i<=size;i++) 101 printf("%d\n",answer[i]); 102 103 return 0; 104 }
代碼寫得很清晰,一共大概100行,主要是定義並查集,和運用並查集檢測周邊四個點的集合數。spa
這代碼能夠經過CCF的1000*1000 1s評測,運行時間大概在700-800ms,使用內存10M。使用內存數在全部實現中最少,可是時間不是最少。排名第一的同窗大概在450ms左右。這個我不清楚如何作到在消除者300ms的差距,由於300ms差距不是簡簡單單優化細節能夠作的。就目測他們應該是保存了更多的數據。.net
有沒有同窗還能更進一步的優化算法或是有更好的想法,爭取再砍下去一半時間。期待你的回覆~~~~~忘不吝賜教~~~~~code