hihoCoder #1151 : 骨牌覆盖问题·二 (矩阵快速幂,DP)
2015-09-03 17:33
411 查看
题意:给一个3*n的矩阵,要求用1*2的骨牌来填满,有多少种方案?
思路:
官网题解用的仍然是矩阵快速幂的方式。复杂度O(logn*83)。
这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次,再来乘以初始矩阵init{0,0,0,0,0,0,0,1}后,变成矩阵ans{x,x,x,x,x,x,x,y},y就是答案了,而x不必管。
主要在这个矩阵的构造,假设棋盘是放竖直的(即n*3),那么考虑在第i行进行填放,需要考虑到第i-1行的所有可能的状态(注意i-2行必须是已经填满了,否则第i行无法填到i-2行去)。放的时候有个规则,就是所放的每块1*2的骨牌,必须放有一半以上是在第i行的,而且不允许放到第i+1行去。其实就是根据3种选择来考虑变换,(1)不放(2)放横(3)放竖。
下图假设即将填第i+1行。
AC代码
还有一种方案仅需0ms。即递推,这个需要研究一下递推式,考虑各种情况的变化。不写了。
思路:
官网题解用的仍然是矩阵快速幂的方式。复杂度O(logn*83)。
这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次,再来乘以初始矩阵init{0,0,0,0,0,0,0,1}后,变成矩阵ans{x,x,x,x,x,x,x,y},y就是答案了,而x不必管。
主要在这个矩阵的构造,假设棋盘是放竖直的(即n*3),那么考虑在第i行进行填放,需要考虑到第i-1行的所有可能的状态(注意i-2行必须是已经填满了,否则第i行无法填到i-2行去)。放的时候有个规则,就是所放的每块1*2的骨牌,必须放有一半以上是在第i行的,而且不允许放到第i+1行去。其实就是根据3种选择来考虑变换,(1)不放(2)放横(3)放竖。
下图假设即将填第i+1行。
#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #define pii pair<int,int> #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=1e5+2; const int mod=12357; int M[8][8]={0,0,0,0,0,0,0,1, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,1, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,1,0,0,0,0,0,1, 1,0,0,1,0,0,1,0}; //初始矩阵M int init[8]={0,0,0,0,0,0,0,1}; //初始状态 int tot[8][8], cur[8][8], grid[8][8]; //临时的矩阵 void mul(int A[][8],int B[][8]) //处理两个8*8的矩阵相乘,并保存到A中 { for(int i=0; i<8; i++) { for(int j=0; j<8; j++) { int tmp=0; for(int k=0; k<8; k++) { tmp+=A[i][k]*B[k][j]; tmp%=mod; } grid[i][j]=tmp; } } memcpy(A, grid, sizeof(grid)); } int cal(int n) { memcpy(tot, M, sizeof(M)); memcpy(cur, M, sizeof(M)); n--; //tot已经是2^0了,所以自减1. while(n) { if(n&1==1) mul(tot, cur); //末位为1时,累乘到tot中 mul(cur, cur); //翻倍 n>>=1; } return tot[7][7]; } int main() { freopen("input.txt", "r", stdin); int n; while(~scanf("%d",&n)) printf("%d\n", cal(n)); return 0; }
AC代码
还有一种方案仅需0ms。即递推,这个需要研究一下递推式,考虑各种情况的变化。不写了。
相关文章推荐
- 九度OJ 题目1121:首字母大写
- Linux C语言程序设计(十五)——进程、线程与信号
- hdoj 3917 Road constructions 【最小割 之 最大权闭合图】
- 【C语言】结构体
- 常用排序算法总结
- 一些学习资料
- 我们总希望通过救赎别人来达到自我救赎
- MapReduce应用实例--排序
- Javascript高级程序设计——面向对象之创建对象
- 不能与直系上司同时参加聚会求最大人数 有根树形DP 最大独立集 poj 3342
- C#判断系统是64位还是32位 支持.net4.0以前的版本
- HTTP状态码
- 历史Linux镜像的问题修复方案
- C++内存管理及指针相关
- C++入门经典 笔记 (第十章)创建指针
- LeetCode_delete-node-in-a-linked-list
- 九度OJ 题目1119:Integer Inquiry
- windows2012 iis配置
- Java基础针对自己薄弱环节总结06(集合全)
- 求一个字符串中连续出现次数最多的子串