见链接
这题需要使用手动简单的模拟一下,原题中的一个测试用例便是一个好的例子,传球只能往左边或右边传,相应的,传球次数减一,我们深搜这个状态直到最终传到第一个人手里。于是得到深搜的主要过程:
f[i][j] = dfs( (i+1)%n,j-1 ) + dfs( (i-1 + n)%n,j-1 );
。其中f[i][j]
代表的是经过j
次传球回到i号人手中
第一次提交的代码如下:
#include<iostream>
#include<cstdio>
using namespace std;const int maxN = 35;
int n,m;
int f[maxN][maxN];//f[i][j] 用于计算"经过j次传球回到i号人手中" //计算"经过j次传球回到i号人手中"
int dfs(int i,int j){ //我也是因为“根据是否是0决定是否返回“导致TLE.if(f[i][j] != -1)return f[i][j];if(j == 0 && i!=0)return 0; //printf("i = %d,j= %dn",i,j);//计算值 //1.(i-1+n)%nf[i][j] = dfs( (i+1)%n,j-1 ) + dfs( (i-1 + n)%n,j-1 ); return f[i][j];
}int main(){ scanf("%d%d",&n,&m);fill(f[0],f[0]+maxN*maxN,-1);f[0][0] = 1;//球本来就在1号手中 dfs(0,m);printf("%dn",f[0][m]);
}
执行结果如下:
看到这样的提交结果,大概能猜到具体的问题。(大概率是程序出现了问题,而不是测试用例导致的超时。因为后面两个测试用例都没有超时,而且我在深搜里用的是记忆化搜索,理应不会出现这种问题。)
我手贱下载了一下未过的测试用例,如下:
输入:
10 29
0输出:
0
根据上面的问题分析(是程序导致死循环而不是测试用例),那么就应该查看是否是深搜的过程中没有及时返回(因为只有不能返回才会导致死循环)。那么是什么地方会出现无法返回呢? 。看dfs()
中的代码:
//计算"经过j次传球回到i号人手中"
int dfs(int i,int j){ if(f[i][j] != 0)return f[i][j];if(j == 0 && i!=0)return 0;//计算值 //1.(i-1+n)%nf[i][j] = dfs( (i+1)%n,j-1 ) + dfs( (i-1 + n)%n,j-1 ); return f[i][j];
}
其中的返回语句只有两句:
if(f[i][j] != 0)return f[i][j];
if(j == 0 && i!=0)return 0;
很清楚,可以看到这里有一个自相矛盾的地方。第二个if的返回值是0(表明该次深搜过程的f[i][j]
已经计算好了),但是第一个if却是根据f[i][j]!=0
来返回,这就导致上一次计算好的,这次还是会计算递归计算,从而导致死循环。
将f[i][j]
初始化为-1,然后再根据是否是-1进行返回,就可以顺利得出答案了。AC代码如下:
#include<iostream>
#include<cstdio>
using namespace std;const int maxN = 35;
int n,m;
int f[maxN][maxN];//f[i][j] 用于计算"经过j次传球回到i号人手中" //计算"经过j次传球回到i号人手中"
int dfs(int i,int j){ if(f[i][j] != -1)return f[i][j];if(j == 0 && i!=0)return 0; //计算值 //1.(i-1+n)%nf[i][j] = dfs( (i+1)%n,j-1 ) + dfs( (i-1 + n)%n,j-1 ); return f[i][j];
}int main(){ scanf("%d%d",&n,&m);fill(f[0],f[0]+maxN*maxN,-1);f[0][0] = 1;//球本来就在1号手中 dfs(0,m);printf("%dn",f[0][m]);
}
4 1
0
本文发布于:2024-02-04 19:31:59,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170714828158821.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |