Homework-04
一、问题描述
本次作业的题目要求利用给定的一组单词生成一个矩阵,矩阵的每个位置由一个字母填充,单词表中的每一个单词可以匹配矩阵中一段连续的序列,这段序列可以是横向,纵向或者是45度斜角方向,单词可以由左向右匹配,也可以逆向匹配。题目将生成的矩阵分为3个等级,任意一个等级要求满足前一级所有要求。第一级要求每个方向上至少出现两个单词,总共四个方向,矩阵横纵规模可以不等,每个单词在矩阵中仅能被覆盖一次,不能存在一行或一列不被任何短语覆盖;第二级要求矩阵横纵相等;第三级要求四个角必须被覆盖。最后返回的矩阵期望能有尽可能小的规模。
二、问题分析
1. 每个单词在矩阵中出现,且只出现1次 2. 上下、下上、左右、右左及对角线共8个方向,每个方向均不少于2个单词排布。 3. 矩阵长宽可以不同 4. 不存在无效行或列 5. (进阶要求)矩阵为正方形 6. (进阶要求)矩阵四角有单词覆盖
我们讨论出的解题思路是枚举+暴力搜索。再进行一部分优化。
三、解题思路
我们的思想是直接做矩阵为正方形的这种情况。因为之前又一次上课我们已经讨论过这道题。
我们的思路是
1.首先把所有的单词按长度由大到小排列
2.8个不同方向我们分别用向量 水平左(-1,0),斜左上(-1,1),竖直上(0,1),斜右上(1,1),水平右(1,0),斜右下(1,-1),竖直下(0,-1),斜左下(-1,-1),
3.然后从字符长度最长的单词开始往里加入。每一次加入时给该单词的第一个位置随机生成一个(x,y),还有一个单词的方向 direct,随机生成很多次,然后就是计算这里得分最高的一组,在result—array的(x,y)处放置该单词的第一个字母,然后按照放置方向direct将该单词全部放入。
4、那么我们的分数是怎么计算的呢,我们的思路是这样的,如果放置的位置已经有了要放置的字母,那么这么放该字母的效率就非常高,所以就加一分。
四、源代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 20 #define maxtry 100000 int totalnum=0; char phrase_array[100][100]; char result_array[100][100]; int DX[8]={-1,-1,0,1,1,1,0,-1}; int DY[8]={0,1,1,1,0,-1,-1,-1}; void sort() { int i,j; char s[100]; for(i=1;i<=totalnum;i++) for(j=i+1;j<=totalnum;j++) if(strlen(phrase_array[i])<strlen(phrase_array[j])){ strcpy(s,phrase_array[i]); strcpy(phrase_array[i],phrase_array[j]); strcpy(phrase_array[j],s); } } void input(FILE **p) { int i=0,j; while(fscanf(*p,"%s",phrase_array[++totalnum])!=-1); totalnum--; sort(); for(i=1;i<=N;i++) for(j=1;j<=N;j++) result_array[i][j]=' '; } void insertword(char *phrase,int location_x,int location_y,int location_d) { int i; for(i=0;i<strlen(phrase);i++) { result_array[location_x][location_y]=phrase[i]; location_x+=DX[location_d]; location_y+=DY[location_d]; } } int calculate(char *phrase,int x,int y,int d) { int i,score=0; for(i=0;i<strlen(phrase);i++) { if(x>N||x<1||y>N||y<1) return -1; else if(phrase[i]==result_array[x][y]) score++; else if(result_array[x][y]!=' ') return -1; x+=DX[d]; y+=DY[d]; } } int locateofrand(char *phrase,int *location_x,int *location_y,int *location_d) { int best=-1; int i,x,y,d,temp; for(i=1;i<=maxtry;i++) { x=rand()%N+1; y=rand()%N+1; d=rand()%8; temp=calculate(phrase,x,y,d); if(temp>best) { best=temp; *location_x=x; *location_y=y; *location_d=d; } } return best; } void workprocess() { int location_x,location_y,location_d,i,j,judge; srand((int)time(0)); for(i=1;i<=totalnum;i++){ judge=locateofrand(phrase_array[i],&location_x,&location_y,&location_d); if(judge==-1){ printf("please change the value of N!\n"); } insertword(phrase_array[i],location_x,location_y,location_d); } } void output(FILE **p) { int i,j; for(i=1;i<=N;i++){ for(j=1;j<=N;j++) fprintf(*p,"%c",result_array[i][j]); fprintf(*p,"\n"); } } int main(int argc, char *argv[]) { FILE *in,*out; in=fopen("input.txt","r"); out=fopen("result.txt","w"); input(&in); workprocess(); output(&out); return 0; }
五、总结
在这次的编程过程中,我们相互促进,共同学习讨论算法,完善判断思路与分数计算条件,虽然最终得出的搜索算法远远不能说是完成所有的要求和效率最高,但是我们已然完成了题目的要求,即8方向,无重复,四角有单词,矩阵最小。与此同时,我们的团队效率也较上次大大提升,面对后续的作业,我们充满信心~!
六、报告
Personal Software Process Stages |
时间百分比(%) |
实际花费的时间 (分钟) |
原来估计的时间 (分钟) |
计划 |
10% | 180 | 120 |
· 估计这个任务需要多少时间,把工作细化并大致排序 |
10% | 180 | 120 |
开发 |
85% | 1530 | 1020 |
· 需求分析 (包括学习新技术) |
15% | 270 | 180 |
· 设计复审 (和同事审核设计文档) |
10% | 180 | 120 |
· 代码规范 (制定合适的规范) |
5% | 90 | 60 |
· 具体设计 |
10% | 180 | 120 |
· 具体编码 |
35% | 630 | 420 |
· 代码复审 |
5% | 90 | 60 |
· 测试(自我测试,修改代码,提交修改) |
5% | 90 | 60 |
总结报告 |
5% | 90 | 60 |
总计 | 100% | 总用时 1800 | 总估计的用时 1200 |