hdu 5925.Coconuts
http://acm.hdu.edu.cn/showproblem.php?pid=5925
题意:求一个图有多少连通块,按增序输出,但是图比较大需要离散化
像个傻子一样想了一下午怎么根据给出的点求能不能围成封闭曲线再求面积......结果gg,想不出可行的方法。只能去网上看dalao们的代码了.....
看完才知道要什么离散化,离散化以后dfs一下就好了,超简单........无知真可怕
然后开始打,因为坐标我变懵逼了,dfs没处理好边界tle,然后.......还是因为坐标的问题,有多个相同行列坐标的时候我忘了更新后面的,结果数组又越界,最后终于改对,这么简单的题.........哎,心痛
二维离散化:把一张图压缩一下,合并那些连续的空白行列(把多个连续空白行合并成一行,不能把那些有用的块完全贴在一起)
右边是离散化后的新图可以看出来整个图变得更加紧凑了(被红色圈起来的方块),那些多个连续的空白行完全可以用一行代替(右图灰色的行列)
将坐标分别存放,先只看(x,y)中的x,把所有x从小到大排序(在其中加入0和原本图的这一边的长度,0作为第一个输入的x离散化的标志,另一个作为图的边界,他被离散化后就是新图的新边长)
用每一个x和上一个比较,s[i][0]-s[i-1][0]≥2的话说明他们之间最少有2行连续的空白,把这些空白合并。用一个标志p来表示新图的新下标,每从原图中拿一个点放在新图中(如果不和上一个放入的点同行)就让p++,没有空行出现的时候p也要++,p每次都代表这个新放入的点(或者空白行)的新x
要注意好原坐标和变化后坐标直接是怎么对应的,以及新图的大小。
1 #include<iostream> 2 #include<algorithm> 3 #include<string.h> 4 #define ll long long 5 using namespace std; 6 struct node//存一个坐标的x值或者y值,完整坐标存在s[p]中 7 { 8 int n,p; 9 bool operator < (node b) 10 { 11 return n<b.n; 12 } 13 }; 14 15 node r[207]={0},c[207]={0};//分别存x和y的值 16 int s[207][2]={0};//完整坐标 17 int map[500][500]={0};//离散化后的map在map[x][0]和map[0][y]中存的是本行/列代表原来的几行/列 18 ll ans[40005];//存答案 19 int R,C,N,n; 20 ll dfs(int x,int y)//dfs 21 { 22 ll an=1; 23 an = an * map[x][0]*map[0][y]; 24 map[x][y]=1; 25 if(x-1>0&&!map[x-1][y])an+=dfs(x-1,y); 26 if(y-1>0&&!map[x][y-1])an+=dfs(x,y-1); 27 if(x+1<s[n][0]&&!map[x+1][y])an+=dfs(x+1,y); 28 if(y+1<s[n][1]&&!map[x][y+1])an+=dfs(x,y+1); 29 return an; 30 } 31 32 int main() 33 { 34 int T,t=0; 35 scanf("%d",&T); 36 while(t++<T) 37 { 38 memset(map,0,sizeof(map));//初始化 39 memset(r,0,sizeof(r));// 40 memset(c,0,sizeof(c));// 41 memset(s,0,sizeof(s));// 42 43 printf("Case #%d:\n",t); 44 scanf("%d %d",&R,&C); 45 scanf("%d",&N); 46 n=1; 47 while(n<=N)//从1开始存。空出(0,0)的位置,(0,0)要作为参考,以为每个坐标压缩时都是以左上角的另一个坐标为标准 48 { 49 scanf("%d %d",&r[n].n,&c[n].n);//分别存下x和y 50 s[n][0]=r[n].n;//再统一存在s中 51 s[n][1]=c[n].n; 52 r[n].p=n;//这个x的完整坐标在s中对应的下标 53 c[n].p=n; 54 n++; 55 } 56 57 r[n].n=R+1;//存下(R,C)当做边界 58 r[n].p=n; 59 c[n].n=C+1; 60 c[n].p=n; 61 s[n][0]=R+1; 62 s[n][1]=C+1; 63 64 sort(r+1,r+n);//对行离散化 65 int i=1; 66 int p=0; 67 while(i<=n) 68 { 69 if(r[i].n - r[i-1].n >= 2)//本点和左上角的另一个点的x坐标之间至少间隔一个的话,把间隔的多格压缩到1格中来表示 70 { 71 map[++p][0]=r[i].n-r[i-1].n-1;//记录把多少压缩到了一格 72 } 73 if(r[i].n != r[i-1].n)//如果本点和上一点不在同一直线上,把p向下移一格,移过后p就是本点对应到离散化后的map中的新x值 74 { 75 map[++p][0]=1; 76 } 77 s[r[i].p][0]=p;//更新坐标,把原坐标对应到离散化的坐标系中 78 i++; 79 } 80 81 sort(c+1,c+n);//离散化y 82 i=1; 83 p=0; 84 while(i<=n) 85 { 86 if(c[i].n - c[i-1].n >= 2) 87 { 88 map[0][++p]=c[i].n-c[i-1].n-1;//记录把多少压缩到了一格 89 } 90 if(c[i].n != c[i-1].n) 91 { 92 map[0][++p]=1; 93 } 94 s[c[i].p][1]=p;//更新坐标 95 i++; 96 } 97 i=1; 98 while(i<n) 99 { 100 map[ s[i][0] ][ s[i][1] ]=1;//根据离散化后的坐标在map中标出不可行的点 101 i++; 102 } 103 i=1; 104 int j=1; 105 p=0; 106 while(i<s[n][0])//遍历离散化后的map 107 { 108 j=1; 109 while(j<s[n][1]&&j<500) 110 { 111 if(!map[i][j]) 112 { 113 ans[p++]=dfs(i,j); 114 } 115 j++; 116 } 117 i++; 118 } 119 120 sort(ans,ans+p); 121 cout << p << endl; 122 i=0; 123 while(i<p) 124 { 125 printf("%I64d",ans[i]); 126 i++; 127 if(i!=p)cout << " "; 128 else cout <<endl; 129 } 130 } 131 return 0; 132 }