程序设计天梯赛个人题解 L2-052 吉利矩阵
dfs.
(去年打比赛的时候有点没敢开这个题,今天做起来发现不是很难,当时不知道为什么没思路)
先考虑了一下一维的情况,即需要控制一排数之和的情况,不难发现只需记录当前还差的数量need,即为(N-之前数的总和).且最后一个数直接=need就行.
二维情况稍加延伸. 记录 所需总和 与 每行/列当前和 的差值need.逐行内逐列遍历. 对于每行的最后一列, 直接填充为Hneed(这样既保证了每行的和是N, 又起到了剪枝的作用, 避免对最后一列的数进行从0到Hneed的遍历, 剪掉了递归末端大量的无用分支). 对于最后一行的数, 由于每列的所需和是固定的, 故也可以直接得出.
最后注意一下dfs的写法和细节部分即可
*另注: 检查时使用"Lneed[i]<0"进行筛选, 是因为在最后一列我们直接使用了Hneed, 这样可能导致最后一列的Lneed被减为负值, 故要筛选一下. 这样的情况造成了多余的递归浪费, 可以看到本代码在此部分还有稍微优化和剪枝的空间.
#include <iostream>
#include <algorithm>
using namespace std;
int L;
int N;
int result = 0;
int Hneed[9]{0};
int Lneed[9]{0};
void dfs(int h, int l)
{
if(h==N-1&&l==0)//倒数第二行最后一个填完后,开始检查
{
int sum=0;
for(int i=0;i<N;i++)
{
if(Lneed[i]<0)
return;
sum+=Lneed[i];
}
if(sum==L)
result++;
return;
}
if (l == N - 1) // 倒数第一列直接填此行的剩余数
{
int i = Hneed[h];
Hneed[h] -= i;
Lneed[l] -= i;
dfs(h + (l + 1) / N, (l + 1) % N);
Hneed[h] += i;
Lneed[l] += i;
}
else
{
int t = min(Hneed[h], Lneed[l]);
for (int i = 0; i <= t; i++)
{
Hneed[h] -= i;
Lneed[l] -= i;
dfs(h + (l + 1) / N, (l + 1) % N);
Hneed[h] += i;
Lneed[l] += i;
}
}
}
int main()
{
cin>>L;
cin>>N;
for(int i=0;i<N;i++)
{
Hneed[i]=L;
Lneed[i]=L;
}
dfs(0,0);
cout<<result;
return 0;
}
/*赛时代码:
#include <iostream>
#include <algorithm>
using namespace std;
// 一维
// int get(int nums,int need)//共有nums个数,需要和为need
// {
// if(nums<=1)
// return 1;
// int res=0;
// for(int i=0;i<=need;i++)//当前
// {
// res+=get(nums-1,need-i);
// }
// return res;
// }
int L;
int N;
int result = 0;
int Hneed[9]{0};
int Lneed[9]{0};
int save[10][10];
void dfs(int h, int l)
{
//cout<<h<<' '<<l<<endl;
// if (h >= N - 1) // 倒数第一行不填充就停止
// return;
//if(h==N-2&&l==N-1)//倒数第二行最后一个填完后,开始检查
if(h==N-1&&l==0)//倒数第二行最后一个填完后,开始检查
{
int sum=0;
for(int i=0;i<N;i++)
{
if(Lneed[i]<0)
return;
sum+=Lneed[i];
//save[N-1][i]=Lneed[i];
}
//cout<<"checking"<<endl;
//cout<<"show:"<<endl;
// for(int i=0;i<N;i++)
// for(int j=0;j<N;j++)
// cout<<save[i][j]<<" \n"[j==N-1];
if(sum==L)
{
result++;
//cout<<"pass"<<endl;
}
return;
}
if (l == N - 1) // 倒数第一列直接填此行的剩余数
{
int i = Hneed[h];
Hneed[h] -= i;
Lneed[l] -= i;
//save[h][l]=i;
dfs(h + (l + 1) / N, (l + 1) % N);
//save[h][l]=-1;
Hneed[h] += i;
Lneed[l] += i;
}
else
{
int t = min(Hneed[h], Lneed[l]);
for (int i = 0; i <= t; i++)
{
Hneed[h] -= i;
Lneed[l] -= i;
//save[h][l]=i;
dfs(h + (l + 1) / N, (l + 1) % N);
//save[h][l]=-1;
Hneed[h] += i;
Lneed[l] += i;
}
}
}
int main()
{
cin>>L;
cin>>N;
for(int i=0;i<N;i++)
{
Hneed[i]=L;
Lneed[i]=L;
}
dfs(0,0);
cout<<result;
return 0;
}
*/

浙公网安备 33010602011771号