IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【题解】[NOIP2018 提高组] 填数游戏 -> 正文阅读

[数据结构与算法]【题解】[NOIP2018 提高组] 填数游戏

题意

构造方案。满足字典序小的权值一定大。

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

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 12:59:14  更:2021-07-30 12:59:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:54:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码