紫书解题报告——一定要总结经验
从第四章开始,之前的都很容易一遍ac
vj紫书链接
题意请看紫书,有对应页码
题目索引
- 第四章:函数和递归
- 73页 Ancient Cipher UVA - 1339
- 79 Hangman Judge UVA - 489
- 82 The Dole Queue UVA - 133
- 83 Message Decoding UVA - 213
- 85 Spreadsheet Tracking UVA - 512
- 89 A Typical Homework (a.k.a Shi Xiong Bang Bang Mang) UVA - 12412
- 95 Xiangqi UVA - 1589
第四章:函数和递归
73页 Ancient Cipher UVA - 1339
重排不仅是有无数可能,同时也是可以是不管顺序,更简单!
只有出现次数需要记录。
79 Hangman Judge UVA - 489
1.出错:
有一个记录这轮有没有找到的
故猜完了就break,后面的不要再记录了,否则win变chickened out
2.加快效率:
记录还剩下多少个,不为0继续
比检查还有没有没去掉的快
82 The Dole Queue UVA - 133
1.循环——取模运算
a[n]中第i号(从1到n)
p= (i+n-1) %n+1;
//知识:-1%n=n-1,
//考虑到1到0,转到n,不可以 p= i %n;
走过,就修改一下,以后只记没修改的就好
2.从1开始数k个,到k,2k,…,那要从0+k开始
相应的,从n开始倒数m个,到n-m+1,n-2m+1,…,那要从n+1开始
相当于哨兵节点,方便很多
(按上面取了余,则分别是n和1)
83 Message Decoding UVA - 213
1.想法:
妙,空间换时间。
直接开code [8] [1<<8] , 把目标字符串存在对应位置
2.注意换行,可把getchar()改为不读换行"\n or \r"的函数
这题挺有意思,代码:
#include
#include
//#include
//#include
//#include
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
int code[8][1<<8];
int readchar()
{char ch;while(1){ch=getchar();if(ch!='\n'&&ch!='\r')return ch;}
}
int readcode()
{if((code[1][0]=readchar())==EOF)return 0;for(int len=2;len<(1<<3);len++){int m=(1<<len)-1;for(int cnt=0;cnt<m;cnt++){ code[len][cnt]=getchar(); if(code[len][cnt]=='\n'||code[len][cnt]=='\r')return 1;}}return 1;
}
int readint(int t)
{int s=0;while(t--){s=s*2+readchar()-'0';}return s;
}
int main()
{while(readcode()){for(int len=readint(3);len;len=readint(3)){for(int cnt=readint(len);cnt!=(1<<len)-1;cnt=readint(len)){putchar(code[len][cnt]);}}putchar('\n');}return 0;
}
85 Spreadsheet Tracking UVA - 512
1.关于重复的教训
循环内分支,比分支内循环,代码简洁不易错
如果复制粘贴,经常有的字母忘记改。只要不卡常,以后怎样copy最少用怎样,时间的常数比copy的错误危害小多了
2.关于结构下数组序号的教训
容易cmd[i].x[j]写成都是i,
或者二重循环就也错了
要注意
3.思路妙:
将所有操作保存,然后对于每个查询,对该格进行每个操作。
不需要整个电子表格一起变化,会更好写,更高效
89 A Typical Homework (a.k.a Shi Xiong Bang Bang Mang) UVA - 12412
1.建议写一段前先把想到的注意点都注下,防止分心忘记,很多就错在这里
2.//发现错误的方法:多加了几个重名人 ,即让数据更大一些
3.查询时,我用了是排名成绩的sort方法
但是错了,因为读英语有
//in the same order they’re added to the database.
紫书上是一个a[i]只用一次,不会删除后再利用解决进入时的顺序问题
//所以排序还不行,并且如果要改对,连储存方式都要改,还是看看紫书算了
//英语要好
4.浮点数误差:
When formatting a floating-point number such as Average Score, a good way to prevent floating-point errors is to add a small number (like 1e-5 in this problem). Otherwise, 80.315 would be printed
as 80.31 if the floating-point error makes it 80.31499999…
即内部存的是有误差的,四舍五入可能出错,所以要+EPS防止出错
95 Xiangqi UVA - 1589
一下午ac了,狂喜
一个我看了才找对思路的题解
开始思路:把棋盘的正在被将的点画上
麻烦:可能重叠将,可能吃子
现在思路:存棋盘,判断将走的四个点,到底能不能至少有一个躲过将军。先看是否对将注意。
具体见下,还有一个输出棋盘的注释,可以看到。
https://blog.csdn.net/sunlanchang/article/details/56682373
一个找到我错的测试数据,tql
是对将的那个发现
https://blog.csdn.net/weixin_30606669/article/details/96243267?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
一个笨笨的常见错误:在外面,命名要对到了!
简化技巧:
(简化不仅省时,而且减少复制粘贴,降低出错可能。实在不行,自己重新写,也不要复制粘贴的风险)
使用宏:
使用中等等级的宏,意思是,不要把文本改了,改了数字就好了,否则乱且报错
使用数组确定方向:可以循环了。注意马,将不共用方向为好,修改时改了马的,没想到将的就走错了。
if(vis[i][y0]=='G'){//wa:少了一个y0的0! win=0;break;//对将 }else if(vis[i][y0]){break;//不是对子
/* POJ4001 HDU4121 UVA1589 UVALive5829 Xiangqi */
#include
#include
#include
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define L 10
#define W 9
#define br(a,b) if(vis[(a)][(b)]=='R')return false;else if(vis[(a)][(b)])break
#define _forplus(i,a,b) for( int i=(a); i<=(b); i++)
#define _forsub(i,a,b) for( int i=(a); i>=(b); i--)
#define bc(a,b) if(vis[(a)][(b)])\if(cnt==0)cnt++;\else if(vis[(a)][(b)]!='C')break;\else return false
#define bh(a,b,c,d) if((a)<1||(a)>L||(b)<1||(b)>W)continue;\if(vis[(a)][(b)]!='H')continue;\if(vis[(c)][(d)])continue;\return false
char vis[12][12]={0};
int x,y;
char ch;
int f[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int fx[8][4]={{-1,2,-1,1},{1,2,1,1},{2,1,1,1},
{2,-1,1,-1},{1,-2,1,-1},{-1,-2,-1,-1},{-2,-1,-1,-1},{-2,1,-1,1}};
int n,x0,y0;
int win=0;
inline char mychar(){int ch=getchar();while(ch<'A'||ch>'Z')ch=getchar();return ch;
}
bool can(int x,int y){//判断是否出界 if(x<1||x>3||y<4||y>6){return false;}//判断是否前方第一个是将 //同y,看xfor(int i=x+1;i<=L;i++){if(vis[i][y]=='G')return false;else if(vis[i][y])break;}//判断是否十字第一个有车_forplus(i,x+1,L){br(i,y);}_forsub(i,x-1,1){br(i,y);}_forplus(j,y+1,W){br(x,j);}_forsub(j,y-1,1){br(x,j);}//判断是否十字第二个有炮int cnt;cnt=0;_forplus(i,x+1,L){bc(i,y);}cnt=0;_forsub(i,x-1,1){bc(i,y);}cnt=0;_forplus(j,y+1,W){bc(x,j);}cnt=0;_forsub(j,y-1,1){bc(x,j);}//判断是否八方有马,且不越界,不bang脚_forplus(i,0,7){bh(x+fx[i][0],y+fx[i][1],x+fx[i][2],y+fx[i][3]);}return true;
}
int main()
{while(~scanf("%d%d%d",&n,&x0,&y0)&&n){//涂点,0可1不可,2落红子 mem(vis,0);for(int i=1;i<=n;i++){ch=mychar();scanf("%d%d",&x,&y);vis[x][y]=ch;}/*//看棋盘 printf("\n ");for(int i=1;i<=9;i++){printf("%d",i);}putchar('\n');for(int i=1;i<=10;i++){printf("%-3d",i);for(int j=1;j<=9;j++){if(i==x0&&j==y0){putchar('J');continue;}else if(!vis[i][j]){putchar('-');continue;}printf("%c",vis[i][j]);}putchar('\n');}*/win=1;//红方win为1 _forplus(i,x0+1,L){if(vis[i][y0]=='G'){//wa:少了一个y0的0! win=0;break;//对将 }else if(vis[i][y0]){break;//不是对子 } }if(win==0){printf("NO\n");}else{//开始判断四点可否走,有一点可走则NO for(int i=0;i<4;i++){if(can(x0+f[i][0],y0+f[i][1])){//true可走,false不可走 win=0;break;}} printf("%s\n",(win?"YES":"NO"));}} return 0;
}
————————————————
版权声明:本文为CSDN博主「出尘呢」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51945248/article/details/115306314
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
