遗憾的是,比赛中没有全部AC。
现在想出来了,和之前做过的一道题很类似,那道题也是PTA上的题目(整数分解为若干项之和),链接放下面了,大家可以看懂这道题之后去尝试做一下。
为什么说类似呢,其实都是深搜+回溯。
我讲一下大概得思路以及注意的细节,然后大家看看代码估计就可以懂啦
当然里面还有一些剪枝,一开始没有优化剪枝会有两个超时(测试点4,5)
思路就是去遍历每一个点,遍历的时候我们给它进行赋值(0~L)即可,然后往下一个点遍历就好了···
第一个细节,题目说的是非负整数(包括0哦)
这里用了一个比较好用的技巧,大家可以记住,以后用起来很方便
样例是3*3的矩阵,我们给他们编号0~8 从左到右 从上倒下
当得到编号i时,我们可以对它进行变换,找到它所在的行列值,具体做法
x=i/3;y=i%3;大家可以自己算几个,没问题的
当我们遍历到i==M(M是N*N)也就是最后一个的下一个时,我们就赋值完了一种矩阵,这时我们可以去判断是否满足条件,这里用到了hang[],lie[]数组记录各行各列的值,很容易想到,我只要判断他们是否都等与L即可,只要不等于就直接返回,否则最后记得加1记录下来。
这样太慢了,没有剪枝,判断还浪费了O(N)的时间,当然下面的代码就超时了,超时2个测试点
也不能说没有剪枝(有一个小小的剪枝,你们发现没)
if(hang[x]>L||lie[y]>L)
return;
#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int L,N,M;
int fz[10][10];
int hang[10];
int lie[10];
int sum=0;
void dfs(int i)
{
if(i==M)
{
for(int j=0;j<N;j++)
if(hang[j]!=L||lie[j]!=L)
return;
sum++;
return;
}
int x=i/N,y=i%N;
if(hang[x]>L||lie[y]>L)
return;
for(int j=0;j<=L;j++)
{
hang[x]+=j;
lie[y]+=j;
dfs(i+1);
hang[x]-=j;
lie[y]-=j;
}
}
int main()
{
cin>>L>>N;
M=pow(N,2);
memset(hang, 0, sizeof(hang));
memset(lie, 0, sizeof(lie));
dfs(0);
cout<<sum;
}
超时就优化一下吧,做做剪枝操作,把判断操作下放到每个行、列的最后一个位置(不理解没关系,其实说的就是这段代码)
if(x==N-1)
{
pl=true;
j=L-lie[y];
}
else if(y==N-1)
{
pl=true;
j=L-hang[x];
}
大家想一想 当我们到的是行的最后一个值时(y==N-1),它的值还有选择吗,是不是就是L-hang[y],使得这一行的值加起来等于L 对吧~ 想想 是没问题的
第二个细节出现了,我第一次写,就写反了
错误代码:
if(x==N-1)
{
pl=true;
j=L-hang[x];
}
else if(y==N-1)
{
pl=true;
j=L-lie[y];
}
有区别嘛~ 当x==N-1时指的是最后一行的每一列的最后一个位置 所以我们需要用到lie[y],而不要想当然得认为(x代表行,我看到x就认为是和hang[]有关系的,比如我~ 看了好多遍,(耶? 没问题啊我去,思路剪枝都没问题,怎么答案错误)终于还是让我找到bug了)
具体实现看完整代码吧~没有注释(我知道是坏习惯,但是我太懒了,一般简单的从来不写~,大家还是写注释养成习惯较好哈)
#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int L,N,M;
int hang[4],lie[4];
int sum=0;
void dfs(int i)
{
if(i==M)
{
sum++;
return;
}
int x=i/N,y=i%N;
for(int j=L;j>=0;j--)
{
if(hang[x]+j>L||lie[y]+j>L)
continue;
bool pl=false;
if(x==N-1)
{
pl=true;
j=L-lie[y];
}
else if(y==N-1)
{
pl=true;
j=L-hang[x];
}
hang[x]+=j;
lie[y]+=j;
dfs(i+1);
hang[x]-=j;
lie[y]-=j;
if(pl) break;
}
}
int main()
{
cin>>L>>N;
M=pow(N,2);
memset(hang, 0, sizeof(hang));
memset(lie, 0, sizeof(lie));
dfs(0);
cout<<sum;
return 0;
}
AC 460ms 搞定La~~~~
大家不懂多多评论区交流,互相请教互相帮助,没准别人一句话就点通你(亲身经历)
期待和大家共同加油,希望大家不断进步!