poj1009 Edge Detection

给一个n * m的矩阵(n * m ≤ 1e9, m ≤ 1e9)A, 求矩阵A'。

定义A'(i, j) = max(abs(A(i, j) - A(u, v))), 其中(u, v)在矩阵内同时在以(i, j)为中心的九宫格范围内。

考虑到矩阵大小,当然不是按照传统方式呈现矩阵,而是用一种流程编码(RLE)的编码方式表示。

编码方式题目已经交代的很清楚了。

看似很棘手的一个题目,对于如此大的数据量感觉似乎无从下手。

注意到题目说明pair数不会超过1e3。

也就是说,相连的重复数字是很多的,这是本题能够被解决的先决条件。

我们定义A(i, j)的位置是(i * width + j)(i, j从0开始)。

我们定义当前pair(i)的最小位置为f(i)。

如果能够知道A'中所有pair的f值,答案即可得到。

然而准确找到所有pair的位置(不重不漏)是困难的,但是找到它们出现的可能位置(允许冗余)则是可行的。

我们断言:A'中所有pair的f值对应的位置(简记为突变位置)若不在某一行的开端,则必在以A中某个突变位置为中心的九宫格范围内。

画图易证。

当突变位置在某一行的起点时候需要特判。

并非所有行都需要特判,只需要在每个pair前两行和后两行进行特判即可,因为中间行周围的元素都和它本身相同。

复杂度落到可控范围内。

这样我们找到所有伪命中点最后再处理一下(去重)就行了,具体实现见代码。

 

 

http://poj.org/problem?id=1009

 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 1e3 + 10;
 8 
 9 struct Point{
10     int v, len;
11     Point(int v = 0, int len = 0) : v(v), len(len) {}
12 };
13 
14 Point P[maxn], Q[maxn * 30];
15 int p[maxn];
16 int k1, k2;
17 int L, N;
18 
19 bool inRange(int x, int y) { return x < N / L && x >= 0 && y >= 0 && y < L; }
20 
21 bool cmp(Point a, Point b) { return a.len < b.len; }
22 
23 int f(int x, int y){
24     int pos = x * L + y + 1;
25     int l = -1, r = k1 - 1;
26     while(r - l > 1){
27         int mid = (r + l) >> 1;
28         if(p[mid] >= pos) r = mid;
29         else l = mid;
30     }
31     return P[r].v;
32 }
33 
34 int F(int x, int y){
35     int ans = -1;
36     for(int i = -1; i < 2; i++){
37         for(int j = -1; j < 2; j++){
38             int nx = x + i, ny = y + j;
39             if(!inRange(nx, ny)) continue;
40             ans = max(ans, abs(f(nx, ny) - f(x, y)));
41         }
42     }
43     return ans;
44 }
45 
46 int Process(int x, int y, int pos){
47     for(int i = -1; i < 2; i++){
48         for(int j = -1; j < 2; j++){
49             int pos1 = pos + i * L + j;
50             int nx = x + i, ny = y + j;
51             if(!inRange(nx, ny)) continue;
52             Q[k2++] = Point(F(nx, ny), pos1);
53         }
54     }
55 }
56 
57 void solve(){
58     k2 = 0;
59     int pos = 0;
60     p[0] = P[0].len;
61     for(int i = 1; i < k1; i++) p[i] = p[i - 1] + P[i].len;
62     for(int i = 0; i < k1; i++){
63         int x = pos / L, y = pos % L;
64         int nex = pos + P[i].len;
65         int nexrow = (nex - 1) / L;
66         Process(x, y, pos);
67         if(y) Process(x, 0, x * L);
68         if(x != nexrow) Process(nexrow, 0, nexrow * L);
69         pos += P[i].len;
70     }
71     sort(Q, Q + k2, cmp);
72     Q[k2].len = N;
73     for(int i = 0; i < k2; i++){
74         int j = i;
75         while(i + 1 < k2 && Q[i].v == Q[i + 1].v) ++i;
76         printf("%d %d\n", Q[i].v, Q[i + 1].len - Q[j].len);
77     }
78 }
79 
80 int main(){
81     //freopen("in.txt", "r", stdin);
82     //freopen("out.txt", "w", stdout);
83     while(~scanf("%d", &L) && L){
84         N = 0;
85         printf("%d\n", L);
86         for(int i = 0; ; i++){
87             scanf("%d%d", &P[i].v, &P[i].len);
88             N += P[i].len;
89             if(!(P[i].v || P[i].len)){
90                 k1 = i;
91                 break;
92             }
93         }
94         solve();
95         puts("0 0");
96     }
97     puts("0");
98     return 0;
99 }
View Code

 

转载于:https://www.cnblogs.com/astoninfer/p/4781902.html

(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
### 解决方案概述 对于 POJ 1009 Edge Detection 的问题,核心在于实现一种基于邻域差异的边缘检测算法。具体来说,给定一个二维数组表示灰度图像,目标是计算每个像素点与其周围八个邻居之间的最大绝对差值,并以此作为新图像对应位置上的像素值。 #### 输入输出说明 程序接收多组测试数据,每组由两个整数 n 和 m 开始,分别代表矩阵的高度和宽度;随后跟着 n 行字符序列描述原始图片的内容。最终应打印出处理后的结果——即应用上述规则变换得到的新图形[^1]。 #### 关键逻辑解析 为了高效完成这项任务,可以采用如下策略: - **边界条件判断**:考虑到位于四角及边界的特殊单元格仅有部分有效邻居,在遍历过程中需特别注意这些情况下的索引范围控制。 - **双重循环结构**:通过嵌套迭代访问整个网格内的每一个元素,针对当前考察对象执行必要的运算操作并更新其对应的输出坐标处数值。 - **临时存储机制**:由于每次仅修改单个位置的数据而不影响其他待测样本,因此可利用额外的一维或二维辅助空间暂存中间状态直至一轮扫描结束再统一赋值回原位。 ```cpp #include <iostream> using namespace std; int main() { int cases; cin >> cases; while (cases--) { int rows, cols; char img[10][10]; cin >> rows >> cols; getchar(); // consume newline for(int i=0; i<rows; ++i){ gets(img[i]); } cout << "Test case #" << endl; for(int r=0;r<=rows;++r){ for(int c=0;c<=cols;++c){ bool isEdge=false; // Check all eight directions... if(r>0 && abs((int)(img[r-1][c]-'A')-(int)(img[r][c]-'A'))>=2) {isEdge=true;} if(c>0 && abs((int)(img[r][c-1]-'A')-(int)(img[r][c]-'A'))>=2) {isEdge=true;} if(r<rows&&abs((int)(img[r+1][c]-'A')-(int)(img[r][c]-'A'))>=2){isEdge=true;} if(c<cols&&abs((int)(img[r][c+1]-'A')-(int)(img[r][c]-'A'))>=2){isEdge=true;} if(r>0&&c>0&&abs((int)(img[r-1][c-1]-'A')-(int)(img[r][c]-'A'))>=2){isEdge=true;} if(r>0&&c<cols&&abs((int)(img[r-1][c+1]-'A')-(int)(img[r][c]-'A'))>=2){isEdge=true;} if(r<rows&&c>0&&abs((int)(img[r+1][c-1]-'A')-(int)(img[r][c]-'A'))>=2){isEdge=true;} if(r<rows&&c<cols&&abs((int)(img[r+1][c+1]-'A')-(int)(img[r][c]-'A'))>=2){isEdge=true;} putchar(isEdge ? '*' : ' '); } puts(""); } if (--cases >= 0) printf("\n"); } } ``` 这段 C++ 实现展示了如何读取输入、构建内部表示形式以及按照指定方式生成输出。值得注意的是,这里假设输入文件中的字母均处于大写区间内 ('A'-'Z'), 并据此进行了 ASCII 值比较来决定是否存在显著变化从而标记为边缘特征[*^3*].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值