【题解】[NOIP2018 提高组] 填数游戏

题意

给你一个 01 矩阵,一条从左上到右下的路径,可以表述为 DR 的字符串和 01 串。构造填数方案,满足 DR 串小的 01 串一定大。

Solution:

考点:数学+搜索+找规律/推式子。

算法一.

性质一: 对于任意 (i,j) 满足 b[i][j]<=b[i-1][j+1], 因为只有这样才不会出现交叉的情况。该条件对于 n=2 是充要条件,加上爆搜可以得到 45pts

性质二:对于 n=3 打表可以发现下列数据:

0 0 0
0 0 1
0 0 0

观察得到 a[0][1]=a[1][0] ,但是会出现交叉情况,此时要求以 (i,j+1) 为左上角的对角线值相等,结合性质一剪枝可以得到 n,m<=8 的方案数,得分 65pts

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
int n,m,cnt,b[15][15];
bool vis[15][1000005];
int ans[15][15];
ll res;
//20 ~ 40 pts
bool check2(int x,int y){
	for(int i=0;i<n;i++) {
		for(int j=0;j<m;j++) {
			vis[i][j]=0;
		}
	}
	int x2,y2;
	for(int i=0;i<x;i++) {
		for(int j=0;j<y;j++) {
			if(vis[i][j]) continue;
			for(x2=i,y2=j;x2 < x && y2 >= 0 && !vis[x2][y2];x2++,y2--) {
				if(b[x2][y2]!=b[i][j]) return 0;
				vis[x2][y2]=1;
			}
		}
	}
	return 1;
}
void dfs1(int i,int j) {
	if(j==m) i++,j=0;
	if(i==n) {
		res++;
		return; 
	}
	for(int k=0;k<2;k++) {
		b[i][j]=k;
		if(i-1 >= 0 && j + 1 < m && (b[i][j] > b[i-1][j+1] || b[i][j] == b[i-1][j+1] && ! check2(i, j+1))) {
			continue;
		}
		dfs1(i,j+1);
	}
}
int main() { 
	scanf("%d%d",&n,&m); if(n>m) swap(n,m);
	ans[8][8]=3626752;
	ans[7][8]=ans[8][7]=1360128;
	if(n<=8&&m<=8) {
		if(ans[n][m]) {
			printf("%d",ans[n][m]);
		}
		else {
			dfs1(0,0);
			printf("%lld",res);
		}

		return 0;
	}
	int x,y; res=1;
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			if(vis[i][j]) continue;
			for(x=i,y=j,cnt=0;!vis[x][y] && x<= n && y >= 1;x++,y--) cnt++,vis[x][y]=1;
			res=res*(cnt+1)%mod;
		}
	}
	printf("%lld",res);
}

算法二.

考虑 n=3 的情况,观察下列数列:

8 36 112 336 1008 3024 9072 27216 81648 244944 ...

观察到从第 3 项开始公比为 3 ,所以直接输出 f[3] * 3^{m-n} ,得分 80pts

算法三.

考虑 n=4 的情况:

16 108 336 912 2688 8064 24192 72576 217728 653184

观察到从第 5 项开始公比为 3

考虑 n=5 的情况:

32 324 1008 2688 7136 21312 63936 191808 575424 1726272

观察到从第 6 项开始公比为 3

所以 f_{n,m}=f_{n}*3^(m-n-1),m>=n+1 ,得分 100pts

算法四.

还是考虑 状压 dp 。注意到 (i,j) 满足 性质2 当且仅当:

  1. b[i][j-1]=b[i-1][j]
  2. (i,j-1)(i-1,j) 满足 性质2

dp{i,S} 表示处理了前 i 条斜线,满足性质 2 的集合为 S 的方案数。对于每一个斜线,枚举分界点然后转移,时间复杂度 O(8^{n-2}logm)

总结:计数类问题的一般解决思路是打表,然后输出方案,从中得到 重要性质 ,不断修正方案。可以考虑 dp

posted @ 2021-07-29 23:28  仰望星空的蚂蚁  阅读(80)  评论(0)    收藏  举报  来源