从第四章开始,之前的都很容易一遍ac
vj紫书链接
题意请看紫书,有对应页码
题目索引
第四章:函数和递归
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<stdio.h>
#include<string.h>
//#include<math.h>
//#include<iostream>
//#include<algorithm>
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<stdio.h>
#include<string.h>
#include<stdlib.h>
#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,看x
for(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