例题6-13 UVA 1103 Ancient Messages 古老象形符号
2016-02-20 12:51
363 查看
简单说下题意:
给你一个H行W列的字符矩阵,他们是压缩后的十六进制矩阵,把每一个字符变成四个二进制数后,1代表黑像素,0代表白像素,问这些像素组成的图案是题目6种的哪一种!
题意有几个需要注意的地方:
书中分析说数白洞个数!但有可能多个图案放在一起,如何分开呢,那就是上下左右不相互有公共边,斜着就不算了!
思路:
1.把他们存到int二维数组里面,1写成-1,0还是0,然后先第一遍dfs,把所有黑色图案编号1,2,3.。。。
2.直接循环扫描,记录每一个图案的边界。缩小dfs范围。
3.第二遍dfs,把不是id的变成id(因为可能有其他编号!),dfs完了,在把这一块恢复!
感觉dfs,循环这么多会超时,结果0.013s就过了!!
最后自己测试几组数据即可!
给你一个H行W列的字符矩阵,他们是压缩后的十六进制矩阵,把每一个字符变成四个二进制数后,1代表黑像素,0代表白像素,问这些像素组成的图案是题目6种的哪一种!
题意有几个需要注意的地方:
书中分析说数白洞个数!但有可能多个图案放在一起,如何分开呢,那就是上下左右不相互有公共边,斜着就不算了!
思路:
1.把他们存到int二维数组里面,1写成-1,0还是0,然后先第一遍dfs,把所有黑色图案编号1,2,3.。。。
2.直接循环扫描,记录每一个图案的边界。缩小dfs范围。
3.第二遍dfs,把不是id的变成id(因为可能有其他编号!),dfs完了,在把这一块恢复!
感觉dfs,循环这么多会超时,结果0.013s就过了!!
最后自己测试几组数据即可!
#include<cctype> #include<cstdio> #include<string> #include<algorithm> #include<iostream> #include<cstring> using namespace std; const int maxn = 500 + 10; char str1[maxn]; int idx[205][205]; int idx2[205][205]; int pos[5000][4]; int r,c,kase; const int INF = 1e8; const int dxx[] = {0,0,1,-1}; const int dyy[] = {-1,1,0,0}; char rev(int num){ if (num == 1)return 'A'; else if (num == 3)return 'J'; else if (num == 5)return 'D'; else if (num == 4)return 'S'; else if (num == 0)return 'W'; else if (num == 2)return 'K'; } void dfs(int x,int y,int id){ idx[x][y] = id; for (int i = 0; i < 4; ++i){ int nx = x + dxx[i]; int ny = y + dyy[i]; if (nx >= 1 && nx <= r && ny >= 1 && ny <= c && idx[nx][ny]==-1)dfs(nx,ny,id); } return; } void dfs2(int x,int y,int id){ idx[x][y] = id; for (int i = 0; i < 4; ++i){ int nx = x + dxx[i]; int ny = y + dyy[i]; if (nx >= pos[id][0]-1 && nx <= pos[id][2]+1 && ny >= pos[id][1]-1 && ny <= pos[id][3]+1 && idx[nx][ny] != id)dfs2(nx,ny,id); } return; } //void print(){ // for (int i = 1 ;i <= r; ++i){ // for (int k = 1; k <= c; ++k){ // printf("%d",idx[i][k]); // } // printf("\n"); // } //} int main() { //freopen("out.txt","w",stdout); while(scanf("%d%d",&r,&c) == 2 && (r || c)){ memset(idx,0,sizeof(idx)); memset(idx2,0,sizeof(idx2)); for (int i = 0; i < 5000; ++i){ pos[i][0]= pos[i][1] = INF; pos[i][2]= pos[i][3] = -INF; } for (int i = 1; i <= r; ++i){ scanf("%s",str1+1); int cnt=4; for (int j = 1; j <= c; ++j){ int id = isalpha(str1[j]) ? str1[j]-'a'+10 : str1[j]-'0'; //cout << id << endl; for (int k = 0; k < 4; ++k){idx[i][cnt-k]=-(id%2);idx2[i][cnt-k]=idx[i][cnt-k];id/=2;} cnt+=4; } } c*=4; int cnt=0,sum=0; for (int i = 1; i <= r; ++i){ for (int k = 1; k <= c; ++k){ if (idx[i][k] == -1){dfs(i,k,++cnt);++sum;} idx2[i][k]=idx[i][k]; } } //print(); // printf("sum = %d\n",sum); for (int i = 1; i <= r; ++i){ for (int k = 1; k <= c; ++k){ if (idx[i][k]!=0){ int cnt=idx[i][k]; if (pos[cnt][0]>i)pos[cnt][0]=i; if (pos[cnt][1]>k)pos[cnt][1]=k; if (pos[cnt][2]<i)pos[cnt][2]=i; if (pos[cnt][3]<k)pos[cnt][3]=k; } } } // print(); string s; sum=0; //print(); for (int i = 1; i <= cnt; ++i){ int si = pos[i][0],sj=pos[i][1]; sum = 0; for (int j = si-1; j <= pos[i][2] + 1; ++j){ for (int k = sj-1; k <= pos[i][3] + 1; ++k){ //cout << si-1 << "- "<< k<<endl; if (idx[j][k] != i){dfs2(j,k,i);++sum;} } } for (int j = si-1; j <= pos[i][2] + 1; ++j){ for (int k = sj-1; k <= pos[i][3] + 1; ++k){ //cout << si-1 << "- "<< k<<endl; idx[j][k] = idx2[j][k]; } } // printf("%d\n",sum-1); s.push_back(rev(sum-1)); } // print(); sort(s.begin(),s.end()); cout << "Case " << ++kase << ": " << s << endl; } return 0; } // //3 1 //2 //5 //2
相关文章推荐
- 英语并列句与标点
- Cook-Torrance光照模型
- C++中自增自减运算符疑惑大全
- iOS: 适配启动图和图标
- input 的属性autocomplete
- 【每日算法】计数&基数&桶&位图排序-简介
- The 5th Zhejiang Provincial Collegiate Programming Contest---ProblemG:Give Me the Number
- bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)
- Sequence operation(线段树区间多种操作)
- 程序员面试金典 1.2 原串翻转
- Android GridView实现自适应正方形
- 编程中的正交原则
- java web面试题,收集
- ZOJ-2975-Kinds of Fuwas【5th浙江省赛】【暴力】
- 数据包从源主机到达目标主机的过程
- java链表初步学习
- 4-题目1023:EXCEL排序
- (转)数据包从源主机到达目标主机的过程
- linux下报错/usr/bin/env: node: 没有那个文件或目录
- 同 一个页面,不同请求路径,如何根据实际场景写JS