今天,在做百练OJ 2816时遇到了问题。 主要不是算法,而是细节,也让我知道了对基础的严格掌握是多么重要,而今天要说的就是scanf("%c",...)这个细节。 看程序:百练OJ 2816红与黑 我的代码(WA的): //ID:百练OJ 2816红与黑 //网站:C++奋斗乐园|C++论坛|算法论坛|ACM/ICPC论坛 //地址:http://www.cppleyuan.com/ //个人主页:www.wutianqi.com //豆瓣小组:http://www.douban.com/group/cppleyuan/ //转载请写上本帖链接及站点名称:”Tanky Woo与ACM一起做过的日子“和“C++奋斗乐园|C++论坛|算法论坛|ACM/ICPC论坛”
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAX_NUM 21
int W, H;
char aTile[MAX_NUM][MAX_NUM];
int dp(int i, int j);
int cnt = 0;
int main()
{
while(scanf("%d %d", &W, &H) == 2 && W != 0 && H
!= 0)
{
memset(aTile, 0, sizeof(aTile));
for(i = 0; i < H; i++)
{
for(j = 0; j < W; j++)
{
scanf("%c", &aTile[i][j]);
if(aTile[i][j] == '@')
{
pos_i = i;
pos_j = j;
}
}
}
printf("%d\n", dp(pos_i, pos_j));
}
return 0;
}
int dp(int i, int j)
{
if(i<0 || i>=H || j<0 || j>=W)
return 0;
if(aTile[i][j] == '#')
return 0;
else
{
aTile[i][j] = '#';
return 1 + dp(i+1, j) + dp(i-1, j) + dp(i,
j+1) + dp(i, j-1);
}
大家可以测试下: 输入: 6 9 ....#. .....# ...... ...... ...... ...... ......
@...
.#..#. 0 0 而输出却不是上面的图案。 这是为什么呢?原来: scanf("%c",...)对于空格和回车键都可以接受(回车键包含回车
和换行2个ASCII码,分别是10和13,但是用scanf("%c")输入时再
输出则是10,这是因为%c只接受一个字符的原因),所以,解决方
法就是加一个getchar(), 代码局部如下:
for(i = 0; i < H; i++)
{
for(j = 0; j < W; j++)
{
scanf("%c", &aTile;[i][j]);
if(aTile[i][j] == '@')
{
pos_i = i;
pos_j = j;
}
}
getchar(); //消除每输入6个字符的
换行的回车键
}
但是会发现问题还是没有解决,这是为什么呢? 再观察,原来在while(scanf())中的回车键也没消除掉。 所以局部改为:
while(scanf("%d %d", &W;, &H;) == 2 && W != 0 && H
!= 0)
{
memset(aTile, 0, sizeof(aTile));
int i, j;
int pos_i, pos_j; // 为"@"的坐标
getchar(); //消除while中scanf的回
车键
for(i = 0; i < H; i++)
{
for(j = 0; j < W; j++)
{
这下应该是对的了吧。 用freopen充定向去测试,把网页上题目给出的数据粘贴到txt中,
测试。。。还是乱,答案错误。 但是,用手动的去测试却发现,居然是对的。这下郁闷了,以为是
在CMD和TXT中的回车键的ASCII不一样,但是 测试都输出10。 终于,发现了是哪错误,原来在TXT中没一行数据末都多出以一个
空格!这就是元凶!记得在以前一道百练的题目 也是手动就是对的,但是freopen就错误了,先开始还以为是
freopen不能这么用,现在看来,十有八九是 同样的原因,下次在把数据从网页粘贴到TXT中要注意了,因为以
前可能对于%d没感觉。但是对于%c就不好说了, 所以在使用scanf("%c")是要格外注意空格和换行。
正题的代码如下(已AC):
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAX_NUM 21
int W, H;
char aTile[MAX_NUM][MAX_NUM];
int dp(int i, int j);
int cnt = 0;
int main()
{
//freopen("input_2816.txt", "r", stdin);
while(scanf("%d %d", &W;, &H;) == 2 && W != 0 && H
!= 0)
{
memset(aTile, 0, sizeof(aTile));
int i, j;
int pos_i, pos_j; // 为"@"的坐标
getchar();
for(i = 0; i < H; i++)
{
for(j = 0; j < W; j++)
{
scanf("%c", &aTile;[i][j]);
if(aTile[i][j] == '@')
{
pos_i = i;
pos_j = j;
}
}
getchar(); //消除没输入6个的换行
的回车键
}
printf("%d\n", dp(pos_i, pos_j));
}
return 0;
}
int dp(int i, int j)
{
if(i<0 || i>=H || j<0 || j>=W)
return 0;
if(aTile[i][j] == '#')
return 0;
else
{
aTile[i][j] = '#';
return 1 + dp(i+1, j) + dp(i-1, j) + dp(i,
j+1) + dp(i, j-1);
}
}
但是,针对有回车和空格的字符输入来说,gets()是一个好的选择
: (gets()版的解法):
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAX_NUM 21
int W, H;
char aTile[MAX_NUM][MAX_NUM];
int dp(int i, int j);
int cnt = 0;
int main()
{
int i, j;
//freopen("input_2816.txt", "r", stdin);
while(scanf("%d %d", &W;, &H;) == 2 && W != 0 && H
!= 0)
{
for(i = 0; i < H; i++)
scanf("%s", aTile[i]);
for(i = 0; i < H; i++)
for(j = 0; j < W; j++)
if(aTile[i][j] == '@')
printf("%d\n", dp
(i, j));
}
return 0;
}
int dp(int i, int j)
{
if(i<0 || i>=H || j<0 || j>=W)
return 0;
if(aTile[i][j] == '#')
return 0;
else
{
aTile[i][j] = '#';
return 1 + dp(i+1, j) + dp(i-1, j) + dp(i,
j+1) + dp(i, j-1);
}
}