pku_1128_Frame Stacking
来源:互联网 发布:java异或 编辑:程序博客网 时间:2024/06/05 06:23
这题在次证明了我的英语水平是多么烂~~
题意:
给一些用A-Z组成的窗框,它们相互覆盖,要求自下往上顺序输出覆盖顺序,如果有多种情况按字母顺序排序输出.
这题数据挺水的~理论上有些数据基本过不了~例如26字母的全排序:
1518AAABBBCCCDDDEEEFFFA.AB.BC.CD.DE.EF.FAAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLG.GH.HI.IJ.JK.KL.LGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRM.MN.NO.OP.PQ.QR.RMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXS.ST.TU.UV.VW.WX.XSSSTTTUUUVVVWWWXXXYYYZZZ............Y.YZ.Z............YYYZZZ............26!的全排列复杂度加上排序复杂度~天呢~
有几种情况要注意
1.多组输出,有不确定的情况全部输出,按字典顺序排列.2.图中的的frame均会给出4条边的情况(一个顶点包括2条边),可以推断出frame的长度和位置.
例如这组数据:
98AAAAAAAAABBBBBBAABCCCCBAABC..CBAABC..CBAABC..CBAABCCCCBAABBBBBBAAAAAAAAA输出是ABC的全排列,而不是: CBA,如果有被包含的框体不算覆盖,08年亚洲赛有一道最简单的题叫 Ugly Windows 求最上面的一个框,我就当按这个算了~读题的问题没办法啊~~~
因为四个边都会露出来,所以不用考虑这样的数据,直接就能求出框体的位置,相对简单很多:
98AAAAAAAAAB....BAABCCCCBAABC..CBAABC..CBAABC..CBAABCCCCBAABBBBBBAAAAAAAAA
基本解题思想:
这道题是枚举构图+回溯拓扑排序的问题,没有什么变形
首先枚举每个点,求其每个字母的左上和右下的坐标:
inline void setPoint(int i,int j){int s=a[i][j]-'A';disp[s].num++;disp[s].x1=min(disp[s].x1,i);disp[s].y1=min(disp[s].y1,j);disp[s].x2=max(disp[s].x2,i);disp[s].y2=max(disp[s].y2,j);}//fun:init()for(int i=0;i<n;++i) {for(int j=0;j<m;++j) {if(a[i][j]=='.')continue;setPoint(i,j);}}
根据坐标构图: 若字母X的FRAME存在对字母X检索边框,若该边框位置被字母N覆盖,这产生一条边N->X,并且X的入度加一.:
void setGraphC(int x1,int x2,int y,int x){//检索横边 char s='A'+x;for(int i=x1;i<=x2;++i) {int t=a[i][y]-'A';if(!_hash[t]&&a[i][y]!='.'&&a[i][y]!=s) {_hash[t]=true;graph[t][x]=1;dis[x]++;}}}void setGraphK(int y1,int y2,int xx,int x){//检索竖边 char s='A'+x;for(int i=y1;i<=y2;++i) {int t=a[xx][i]-'A';if(!_hash[t]&&a[xx][i]!='.'&&a[xx][i]!=s) {_hash[t]=true;graph[t][x]=1;dis[x]++;}}}void setGraph(int x){//检索FRAME边框dis[x]=0;memset(_hash,0,sizeof(_hash));int x1=disp[x].x1;int x2=disp[x].x2;int y1=disp[x].y1;int y2=disp[x].y2;setGraphC(x1,x2,y1,x);setGraphC(x1,x2,y2,x);setGraphK(y1,y2,x1,x);setGraphK(y1,y2,x2,x);}for(int i=0;i<26;++i)if(disp[i].num!=0)num++,setGraph(i);
构图完成后,就拓扑排序的步骤,进行回溯:
void dfs(vector<int> &aa,int cnt){if(cnt==num) {va.push_back(aa);//存储搜索到的数据return ;}for(int i=25;i>=0;--i) {if(dis[i]==-1) continue;if(dis[i]==0) {//删入度dis[i]=-1;for(int j=0;j<26;++j)if(graph[i][j])dis[j]--;aa[cnt]=i; //存储可行点dfs(aa,cnt+1);//递归回溯 //还原状态 dis[i]=0;for(int j=0;j<26;++j)if(graph[i][j])dis[j]++;}}}
最后进行排序输出.
源代码:
#include <myhead.h>typedef struct _point{int x1,y1;int x2,y2;int num;}Point; //存储坐标const int N=33;int n,m,num; //长宽,用到的字符个数bool _hash[N]; char a[N][N]; //源数据int dis[N]; //入度int graph[N][N];//构图的邻接矩阵Point disp[N];vector<vector<int> > va; //存储答案inline void setPoint(int i,int j){int s=a[i][j]-'A';disp[s].num++;disp[s].x1=min(disp[s].x1,i);disp[s].y1=min(disp[s].y1,j);disp[s].x2=max(disp[s].x2,i);disp[s].y2=max(disp[s].y2,j);}void setGraphC(int x1,int x2,int y,int x){char s='A'+x;for(int i=x1;i<=x2;++i) {int t=a[i][y]-'A';if(!_hash[t]&&a[i][y]!='.'&&a[i][y]!=s) {_hash[t]=true;graph[t][x]=1;dis[x]++;}}}void setGraphK(int y1,int y2,int xx,int x){char s='A'+x;for(int i=y1;i<=y2;++i) {int t=a[xx][i]-'A';if(!_hash[t]&&a[xx][i]!='.'&&a[xx][i]!=s) {_hash[t]=true;graph[t][x]=1;dis[x]++;}}}void setGraph(int x){dis[x]=0;memset(_hash,0,sizeof(_hash));int x1=disp[x].x1;int x2=disp[x].x2;int y1=disp[x].y1;int y2=disp[x].y2;setGraphC(x1,x2,y1,x);setGraphC(x1,x2,y2,x);setGraphK(y1,y2,x1,x);setGraphK(y1,y2,x2,x);}//1void init(){num=0;memset(dis,-1,sizeof(dis));memset(graph,0,sizeof(graph));for(int i=0;i<26;++i) {disp[i].num=0;disp[i].x1=disp[i].y1=N;disp[i].x2=disp[i].y2=0;}for(int i=0;i<n;++i)scanf("%s",a[i]);for(int i=0;i<n;++i) {for(int j=0;j<m;++j) {if(a[i][j]=='.')continue;setPoint(i,j);}}//2for(int i=0;i<26;++i)if(disp[i].num!=0)num++,setGraph(i);}inline void delVetx(int x){for(int i=0;i<26;++i)if(graph[x][i])dis[i]--;}//3void dfs(vector<int> &aa,int cnt){if(cnt==num) {va.push_back(aa);return ;}for(int i=25;i>=0;--i) {if(dis[i]==-1) continue;if(dis[i]==0) {dis[i]=-1;for(int j=0;j<26;++j)if(graph[i][j])dis[j]--;aa[cnt]=i;dfs(aa,cnt+1);dis[i]=0;for(int j=0;j<26;++j)if(graph[i][j])dis[j]++;}}}bool cmp(vector<int> aa,vector<int> bb){// 排序时注意逆向排序,因为要求自底向上输出结果,在这里卡了半小时...手生啦~~~size_t mm=num-1;while(aa[mm]==bb[mm]&&mm!=0)mm--;return aa[mm]<bb[mm];}void getResult(){//4sort(va.begin(),va.end(),cmp);vector<int> t;for(size_t i=0;i<va.size();++i) {t=va[i];for(int j=num-1;j>=0;j--) {printf("%c",t[j]+'A');}puts("");t.clear();}for(size_t i=0;i<va.size();++i)va[i].clear();va.clear();}int main(){while(~scanf("%d%d",&n,&m)) {init();//5vector<int> aa(27);//6dfs(aa,0);//7getResult();}return 0;}
- pku_1128_Frame Stacking
- Stacking
- Cube Stacking
- Stacking Boxes
- Cube Stacking
- Cube Stacking
- Cube Stacking
- POJ1988_Cube Stacking
- poj1988Cube Stacking
- Stacking Boxes
- Box Stacking
- Cube Stacking
- Cube Stacking
- Cube Stacking
- Cube Stacking
- Cube Stacking
- stacking context
- stacking简介
- 黑马程序员---java基础之正则表达式
- (整理)C/C++野指针
- NSdata 与 NSString,Byte数组,UIImage 的相互转换
- php相关语法和概念
- XML学习基本理论1
- pku_1128_Frame Stacking
- Android菜单详解(二)——创建并响应选项菜单
- 通过Android-sharedUserId访问不同apk的资源文件(资源和数据库)
- Class.getResource()与Class.getResourceAsStream()方法
- Linux下tomcat的配置
- 自定义Dialog
- java 二维数组
- XML 学习基本理论2
- android导入项目,项目上显示一个叉叉