ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

非皇后

2021-08-19 17:02:45  阅读:211  来源: 互联网

标签:205 格子 走法 复杂度 棋子 皇后


  • 有一个R行C列的棋盘。“皇后”的每一步走法是可以从当前所在的格子走到同一行的任意一个格子、同一列的任意一个格子、所在的两条对角线的任何一个格子。“非皇后”的每一步走法与“皇后”的走法刚好相反,凡是“皇后”能走到的格子,“非皇后”都不能走;凡是“皇后”不能走的格子,“非皇后”都能走。

  • 现在你要把一个棋子放到棋盘的任意一个格子,然后该棋子每一步都要按照“非皇后”的走法,恰好走N步,注意每一步都要走,不能停留。把该棋子经过的这\(N+1\)个格子看是一个排列,就得到一种方案。问有多少种不同的合法方案。答案模\(1000000007\)。

  • \(1 \leq R,C,N \leq 200\)

  • 限时:\(2s\)


看到这道题,可以马上想到\(DP\)

开一个数组\(f[i][j][k]\),\(i\)表示现在枚举到第\(i\)行,\(j\)表示现在枚举到第\(j\)列,\(k\)表示现在走了第\(k\)步。

因为刚开始棋子可以摆在任意位置,所以\(f[i][j][0]\)都为\(1\)。


  • 先从最简单的入手\(\Longrightarrow\) 假如棋子是按皇后的走法

对于一个格子,他可以从同行、同列格子转移而来,他还可以从同对角线的格子而来

时间复杂度:\(O(n^4)\)


  • 接着思考\(\Longrightarrow\) 假如棋子是按非皇后的做法

在上面讲过,若棋子是按皇后的走法,一个格子是由同行、同列、同对角线转移而来。而棋子若是按皇后的走法,一个格子就不是由同行、同列、同对角线转移而来。这恰好是相反关系。相当于我们只要用全部可转移方案减去皇后走法的实际转移结果。

\(f[i][j][k]=\sum\limits_{p=1}^C\sum\limits_{q=1}^Cf[p][q][k-1]-f[i][j][k]\)

时间复杂度:\(O(n^4)\)


  • 优化

虽然目前的时间复杂度\(O(n^4)\),但是\(200^4\)依旧十分庞大,肯定有些数据点会\(TLE\)。

我们发现我们程序唯一做的重复操作便是第一步,也就是统计棋子按皇后走法方案

比如说在\(f[i][j][k]\)这个节点,他可以从同行的格子转移而来,而\(f[i][j+1][k]\)这个节点也能从同行的格子转移而来。显然两次操作有所重复,这时我们只要用到部分和便可以优化时间了。

优化后时间复杂度: \(O(n^3)\)


上代码

#include<bits/stdc++.h>
using namespace std;
int R,C,n,b,c;
long long h[205],l[205],zx[405],yx[205][205],f[205][205][205];
const int MOD=1000000007;
long long sum,ans;
int main()
{
  scanf("%d%d%d",&R,&C,&n);
  for(int i=1; i<=R; i++)
    for(int j=1; j<=C; j++)
      f[i][j][0]=1;
  for(int i=1; i<=n; i++)
  {
  	sum=0;
  	for(int j=1; j<=R; j++)h[j]=0;
	for(int j=1; j<=C; j++)l[j]=0;  
	for(int j=2; j<=R+C; j++)zx[j]=0;
	for(int j=1; j<=C; j++) yx[1][j]=0;
	for(int j=2; j<=R; j++) yx[j][1]=0;
	for(int j=1; j<=C; j++){b=1;c=j;while(b<=R&&c<=C) yx[1][j]=(yx[1][j]+f[b][c][i-1])%MOD,b++,c++;}
	for(int j=2; j<=R; j++){b=j;c=1;while(b<=R&&c<=C) yx[j][1]=(yx[j][1]+f[b][c][i-1])%MOD,b++,c++;}
  	for(int j=1; j<=R; j++)
	  for(int k=1; k<=C; k++)
	  h[j]=(h[j]+f[j][k][i-1])%MOD;
	for(int j=1; j<=R; j++)
	  for(int k=1; k<=C; k++)
	  l[k]=(l[k]+f[j][k][i-1])%MOD;
	for(int j=2; j<=R+C; j++)
	{
	  b=1; c=j-b;
	  while(c>C) b++,c--;
	  while(c>0&&b<=R)zx[j]=(zx[j]+f[b][c][i-1])%MOD,b++,c--;
	}
    for(int j=1; j<=R; j++)
	  for(int k=1; k<=C; k++)
	  {
	  	sum+=f[j][k][i-1];
	  	f[j][k][i]=(f[j][k][i]+l[k]-f[j][k][i-1])%MOD;
	  	f[j][k][i]=(f[j][k][i]+h[j]-f[j][k][i-1])%MOD;
	  	f[j][k][i]=(f[j][k][i]+yx[j-min(j,k)+1][k-min(j,k)+1]-f[j][k][i-1])%MOD;
	  	f[j][k][i]=(f[j][k][i]+zx[j+k]-f[j][k][i-1])%MOD;
	  }
	for(int j=1; j<=R; j++)
	  for(int k=1; k<=C; k++)
	  f[j][k][i]=(sum-f[j][k][i-1]-f[j][k][i])%MOD;
  }
  for(int i=1; i<=R; i++)
    for(int j=1; j<=C; j++) ans=(ans+f[i][j][n])%MOD;
  cout<<ans;
  return 0;
}

标签:205,格子,走法,复杂度,棋子,皇后
来源: https://www.cnblogs.com/zeromclai/p/15162629.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有