的题目难不倒哪里去,看到题目的第一反应就是数据结构书里的括号匹配问题,再看看,题目中有一句 well-formed string of parentheses,我猜想是左右括号完美匹配,这样肯定会简单很多。接着看到p、w两组数据感觉两者之间很可能存在函数关系,可以直接转换,想了十来分钟,没想出来,决定用一种很傻的方法。
- 思路
- 用一个数组blk[]来模拟一个栈,保存还没匹配的左括号,大小为size
- j<-[0,2*n),每当遇到j=p[i],也即是遇到右括号,则将blk[size-1]存于数组lBlk[](保存左括号位置),右括号位置j保存于rBlk[]
- 处理lBlk,当前处理j,计算<j的位置上>lBlk[j]的元素的个数,+1,即为对应的w[j]
- 问题
- 思路2中的rBlk明显多余
- 很明显,lBlk、rBlk几乎没有处理,可以确定是赋值处出了错。遇到右括号的语句是if (j == p[cntP]),本意是cntP初值为0,随后根据情况+1,问题就出来遗漏了+1语句,导致只有rBlk[0]也即第一个p[0]时进行了赋值,后面由于cntP一直没有变,当j变化了,p数组中不可能再存在与j不相等的情况。
- 前面几行为blk数组的输出,可以看到只成功执行一次(j:3-4),后面再也没有成功。当时在出现问题2的错误输出时,并没有第一时间想到响应的错误,于是把每次循环中blk的状况也输出了,这样错误就更明显的。
- 问题2、3给我一个教训:只成功运行一次,很可能是下标没有变化,很容易联想到,在某些情况下忘记重置变量的值也会出现类似的情况。
- 在这里,在成功运行第一次后([j:3-4]),数组元素数量一直在减少,在[j:6]后一直增加。对着代码想了十几分钟,完全没有头绪。于是决定跳离代码,看"草稿"(思考思路的时候在本子上写的过程),因为思路简单,很快找到了问题所在:思路2不够完善,在思路2中,p[j]和j第一次相等后再也没有出现相等的情况,修改只需要一句语句:在读入p时对其进行处理:p[j] += j,j是读入p的元素序号。
- 这次blk、rBlk正确了,但是lBlk却有错误,在代码中查看相关赋值语句 lBlk[cntLBlk++] = blk[size]; 貌似没有问题,接着我决定检查语句中另外两个变量,cntLBlk明显没有问题,在看size
if (j != p[cntP])
{
blk[size] = j;
++size;
}
else
{ /* 遇到右括号 */
lBlk[cntLBlk++] = blk[size];
rBlk[cntRBlk++] = j;
--size;
++cntP;
}
从第四行可以看出,size保存的是数组大小,倒数第五句赋值语句引用了一个不存在的地方!明显应该改为size-1 - 以上都是只输入一组数据的情况下的,多组怎么办?因为每次的n是不同的,很自然想到利用**w以及malloc realloc,平时多是使用指针动态分配内存,而像这样“一维”大小不相等的没用过,真用起来了发觉还是比较简单,不过因为不熟悉,也会出现一些细节问题,关键代码
sumN += n[i];
w = (int **)realloc(w, sumN * sizeof(int));
*(w+i) = (int *)malloc(n[i] * sizeof(int));
最惨重的跟头栽在realloc sunN上,突然觉得自己这里用得还是有点小聪明的(菜鸟自我安慰一下)。
- 总结
- 题目不难,而且我觉得肯定有很好的方法而不是像我这么傻这样做的,有用找高手的代码来学习学习。
- 可是在细节处理上经常出错,凭借一些测试,还算是比较好地找到了问题所在。
- 写博客真累,代码写了接近2小时,可是写这篇逻辑混乱的文章用了接近1小时,可是没办法,不总结,不做笔记的话,题目岂不是白做了?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>/* #define TESTPRINT 1 */
int main()
{
int size; /* 处理到目前最后一个右括号的位置 */
int t; /* 测试用例组数 */
int *n; /* p元素个数 */
int *p, **w;
int *lBlk, *rBlk; /* 左右括号的位置,11对应 */
int *blk;
int sumN = 0; /* sum of n[0...i] */int i, j, k;
int cntBlk, cntP, cntLBlk, cntRBlk;scanf("%d", &t);
assert(1<=t && t<=10);n = (int *)malloc(t * sizeof(int));
w = (int **)malloc(sizeof(int)); /* 为了能够使用realloc */
for (i = 0; i < t; ++i)
{
scanf("%d", n+i);
assert(1<=n[i] && n[i]<=20);
sumN += n[i];
w = (int **)realloc(w, sumN * sizeof(int));
*(w+i) = (int *)malloc(n[i] * sizeof(int));p = (int *)malloc(n[i] * sizeof(int));
lBlk = (int *)malloc(n[i] * sizeof(int));
rBlk = (int *)malloc(n[i] * sizeof(int));
blk = (int *)malloc(2 * n[i] * sizeof(int));for (j = 0; j < n[i]; ++j)
{
scanf("%d", p+j);
p[j] += j;
w[i][j] = 1;
}size = cntBlk = cntP = cntLBlk = cntRBlk = 0;
for (j = 0; j < 2*n[i]; ++j)
{
if (j != p[cntP])
{
blk[size] = j;
++size;
}
else
{ /* 遇到右括号 */
lBlk[cntLBlk++] = blk[size-1];
rBlk[cntRBlk++] = j;
--size;
++cntP;
}
}for (j = 0; j < n[i]; ++j)
{
for (k = 0; k < j; ++k)
{
if (lBlk[j] < lBlk[k])
{
++w[i][j];
}
}
}#ifdef TESTPRINT
printf(" w LeftBlanket RightBlanket\n");
for (j = 0; j < n[i]; ++j)
{
printf("%4d %10d %10d\n", w[i][j], lBlk[j], rBlk[j]);
}
#endif
}
#ifndef TESTPRINT
for (i = 0; i < t; ++i)
{
for (j = 0; j < n[i]; ++j)
{
printf("%d ", w[i][j]);
}
printf("\n");
}
#endifreturn 0;
}
[time]9-9-2012