牛客练习赛19-C-托米航空公司

链接: https://www.nowcoder.com/acm/contest/111/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

托米老师靠才华与颜值发家致富后,开了一家航空公司,公司的口号是“您想飞,我们便做您的翅膀~让您每次飞行都有独特的体验!”
但是现在有一个小小的问题需要解决,托米家的飞机每排有M个座位,有N排座位。因此座椅形成了M × N的网格(忽略过道),公司为每次航班都出售K张票。
为了满足口号中的“翅膀”部分,座位必须遵守以下规则:座位被占用时,座位正前方和座位后方的座位以及当前座位左边和右边必须是空的(大概是因为这个飞机会很大吧,boss就是这么任性哼)。
然后为了满足口号中的“独特体验”部分。公司则是对每一趟航班飞机的座位采取不同的安排,如果这一趟的某个座位是占用的,而另一趟的座位是空的,则这两趟飞机座位安排是不同的。
给你三个数字M,N和K。
现在需要从这些座位中选出k个合法的座位。由于这个数字可能非常大,我们只求它对420047取模的结果。

输入描述:

输入的第一行包含一个整数T,表示指定测试用例的数量。
每个测试用例前面都有一个空白行。
每个测试用例由包含三个整数M,N和K的一行组成。

输出描述:

对于每个测试用例输出一行,表示答案对420047取模的结果。


#include <bits/stdc++.h>

#define ll long long
using namespace std;
int a[85][85];
int dir[5][2]={-1,0, 1,0, 0,-1, 0,1, 0,0};//表示前后左右四个方向,多一个0,0是为了标记自身
int n,m;
int mod=420047;
int dfs(int k,int x)//k表示还要选多少个座位,x是已经遍历过多少座位 
{
if(k==0)
return 1;
int res=0;
for(int i=1;i<=n;i++)
   for(int j=1;j<=m;j++)
      {
       if(i*m+j<x)//i*m+j是当前座位序号,排数乘m加上第几列,最大序号是n*m
       continue;//由于后面的遍历序号一定变大,小就跳过
       if(a[i][j]==0)
       {
        for(int k=0;k<5;k++)
         a[i+dir[k][0]][j+dir[k][1]]++;//标记附近点和自身
         res+=dfs(k-1,i*m+j);
         res%=mod;
         for(int k=0;k<5;k++)
         a[i+dir[k][0]][j+dir[k][1]]--;//解除标记
 }
  }
return res;
}
int main()
{
int t;
memset(a,0,sizeof(a));
scanf("%d",&t);
while(t--)
{
int k;
scanf("%d %d %d",&n,&m,&k);
int ans=dfs(k,0);
printf("%d\n",ans);
}
return 0;

猜你喜欢

转载自blog.csdn.net/qq_41603898/article/details/80543996