【题解】[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


__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530307.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(44)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示