转自:https://blog.csdn.net/CatDsy/article/details/81876341

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define pi acos(-1)
#define pii pair<int,int>
const int INF = 0x3f3f3f3f;
const double eps = 1e-;
const int MAXN = 2e3 + ;
const int MAXM = 2e6 + ;
const ll mod = ; char s[MAXN][MAXN];
ll tot[MAXN][MAXN], same[MAXN][MAXN];
ll pre_tot[MAXN][MAXN], pre_same[MAXN][MAXN]; int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
scanf("%d",&t);
while(t--) {
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i = ; i <= n; i++)
scanf("%s",s[i] + );
for(int i = ; i <= n; i++)
pre_tot[i][] = pre_same[i][] = ;
for(int i = ; i <= m; i++) {
tot[][i] = ;
pre_tot[][i] = i;
if(i == || s[][i] != s[][i - ]) same[][i] = ;
else same[][i] = ;
pre_same[][i] = pre_same[][i - ] + same[][i];
}
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
int l = max(j - k, ), r = min(j + k, m);
tot[i][j] = (pre_tot[i - ][r] - pre_tot[i - ][l - ] + mod) % mod;
l = max(j - k + , ), r = min(j + k, m);
tot[i][j] = (tot[i][j] - (pre_same[i - ][r] - pre_same[i - ][l - ] + mod) % mod + mod) % mod;
pre_tot[i][j] = (pre_tot[i][j - ] + tot[i][j]) % mod;
if(j == || s[i][j] != s[i][j - ]) same[i][j] = ;
else {
l = max(j - k, ), r = min(j + k - , m);
same[i][j] = (pre_tot[i - ][r] - pre_tot[i - ][l - ] + mod) % mod;
l = max(j - k + , ), r = min(j + k - , m);
same[i][j] = (same[i][j] - (pre_same[i - ][r] - pre_same[i - ][l - ] + mod) % mod + mod) % mod;
}
pre_same[i][j] = (pre_same[i][j - ] + same[i][j]) % mod;
}
}
ll ans = ;
for(int i = ; i <= m; i++)
ans = (ans + tot[n][i] - same[n][i] + mod) % mod;
printf("%lld\n",ans);
}
return ;
}

题目描述:

给定一个N∗MN∗M的01矩阵

K-seam是满足以下条件的整数序列a:

  • |a|=n,ai∈[1,m]|a|=n,ai∈[1,m]
  • |ai−ai+1|≤K,i∈[1,n)|ai−ai+1|≤K,i∈[1,n)

对于第ii行,删除第aiai个数,会得到一个N∗(M−1)N∗(M−1)的矩阵

不同的整数序列可能会得到相同的矩阵

问:可以得到多少种不同的矩阵


题解:

如果无视different的条件 
定义状态:dp[i][j]dp[i][j]——删除第 ii 行第 jj 个数可以得到的矩阵总数 
可推得转移方程如下:

 
dp[i][j]=∑x=j−kj+kdp[i−1][x]dp[i][j]=∑x=j−kj+kdp[i−1][x]

在此基础上,加上different的条件 
定义状态:

  • tot[i][j]tot[i][j]——删除第 ii 行第 jj 个数可以得到的不同的矩阵总数
  • same[i][j]same[i][j]——删除第 ii 行第 jj 个数和删除第 ii 行第 j−1j−1 个数后得到的相同方案数

那么,tot[i][j]tot[i][j]的状态转移方程为:

 
tot[i][j]=∑x=j−kj+ktot[i−1][x]−∑x=j−k+1j+ksame[i−1][x]tot[i][j]=∑x=j−kj+ktot[i−1][x]−∑x=j−k+1j+ksame[i−1][x]

如果 Matrix[i][j]≠Matrix[i][j−1]Matrix[i][j]≠Matrix[i][j−1] 那么,same[i][j]=0same[i][j]=0 
否则,对于第 jj 个和第 j−1j−1 个的转移区间分别为[j−k,j+k][j−k,j+k],[j−1−k,j−1+k][j−1−k,j−1+k],那么它们的交叉区间为[j−k,j−1+k][j−k,j−1+k],即:从该区间内转移得到的方案数会重复计算一次。得到 same[i][j]same[i][j] 的转移方程为:

 
same[i][j]=∑x=j−kj+k−1tot[i−1][x]−∑x=j−k+1j+k−1same[i−1][x]same[i][j]=∑x=j−kj+k−1tot[i−1][x]−∑x=j−k+1j+k−1same[i−1][x]

时间复杂度为O(n∗m2)O(n∗m2),对于∑∑做前缀和优化,时间复杂度降为O(n∗m)O(n∗m)

最后,对于第n行计算总的不同的方案数,即ans=∑tot−∑same

最新文章

  1. js自动切换图片
  2. #20145205 《Java程序设计》第5周学习总结
  3. jquery操作select(增加,删除,清空)
  4. TCP发送接口的返回值
  5. Oracle操作语言分类
  6. 紧张:飞测独家のJmeter秘籍,限量发放
  7. R语言缺失值信息处理
  8. C语言连接MySQL数据库(课程设计总结)
  9. java程序练习:数组中随机10个数中的最大值
  10. Python中异常(Exception)的总结
  11. Git全解析之用起来先
  12. PLSQLDeveloper过期要注册表
  13. 初探JavaScript魅力(五)
  14. 1.3:Render Pipeline and GPU Pipeline
  15. 52 和 52Rc 通过IIC写入数据
  16. 【转】console.log 用法
  17. 15.vue动画&amp; vuex
  18. 3386 二分图 洛谷luogu [模版]
  19. PAT A1110 Complete Binary Tree (25 分)——完全二叉树,字符串转数字
  20. BOE系统与BW系统间的单点登录(注:这里先简单写一下,改天有时间再进行详细的描述)

热门文章

  1. 使用jbc查询数据封装成对象的工具类
  2. SQLite进阶-19.常用函数
  3. HDU 4417-Super Mario-线段树+离线
  4. java-filter and listener
  5. php 获取城市ip
  6. Linux下mysql创建用户并设置权限,设置远程连接
  7. QT调用CHM方法
  8. 浅谈Promise原理与应用
  9. 在vue中引用echarts导致Cannot read property getAttribute of null ?
  10. UART串口简介