HDU - 6578 Blank

题意

给你\(\{0,1,2, 3\}\)四个数,分别填入长度为\(n\)的数列中,有\(m\)个限制条件,\(l_{i}, r_{i}, x_{i}\)表示在\([l_{i}, r_{i}]\)区间内,只能有\(x_{i}\)个不同的数。问一共有多少总方案。

思路

首先, 我们可以用\(dp[i][j][k][w]\)来表示方案数,\(i, j, k, w\)不是特指对应某个数字,而是四种不同的数字从小到大最后出现的位置\((i < j < k <w)\)。

那么我们就能推出\(dp\)方程

\[dp[i][j][k][w] += dp[i][j][k][w-1]$$ $$dp[i][j][w-1][w] += dp[i][j][k][w-1]$$ $$dp[i][k][w-1][w] += dp[i][j][k][w-1]$$ $$dp[j][k][w-1][w] += dp[i][j][k][w-1]
\]

我们发现后一位都只与\(w-1\)有关,\(100^{4}\)的空间太大,所以我们要做一个优化,把最后一维改成大小为\(2\)的滚动数组

那么我们现在的\(dp\)方程为

\[dp[i][j][k][now] += dp[i][j][k][pre]$$ $$dp[i][j][pre][now] += dp[i][j][k][pre]$$ $$dp[i][k][pre][now] += dp[i][j][k][pre]$$ $$dp[j][k][pre][now] += dp[i][j][k][pre]$$ $$now = (pre+ 1)\%2 = pre \oplus1
\]

转移\(dp\)的时候考虑一下限制条件就\(OK\)啦

AC代码

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int> typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e2 + 10;
const int maxm = 1e5 + 10;
const ll mod = 998244353;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std; int n, m;
int cas, tol, T;
ll dp[maxn][maxn][maxn][3];
vector< pair<int,int> > lim[maxn];
int check(int a, int b, int c, int d){ //a < b < c < d
for(int i = 0; i < lim[d].size(); i++){
int x = lim[d][i].se;
int l = lim[d][i].fi;
if(x == 1 && l <= c)
return 0;
if(x == 2 && (l <= b || l > c))
return 0;
if(x == 3 && (l <= a || l > b))
return 0;
if(x == 4 && (l > a))
return 0;
}
return 1;
} int main() {
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
int l, r, x;
for(int i = 1; i <= n; i++){
lim[i].clear();
}
for(int i = 1; i <= m; i++){
scanf("%d%d%d", &l, &r, &x);
lim[r].push_back(make_pair(l, x));
} dp[0][0][0][0] = 1;
int now = 1;
ll ans = 0;
for(int w = 1; w <= n; w++){
for(int k = 0; k <= w;k++){ //每次初始化,据说memset会T,要手动初始化
for(int j = 0; j <= k; j++){
for(int i = 0; i <= j; i++){
dp[i][j][k][now] = 0;
}
}
}
for(int k = 0; k < w; k++){
for(int j = 0; (!k && j <= k) || j < k; j++){ //(!k&&j <=k):比自己后一位为0的时候,本身也能等于0,反之小于后一位
for(int i = 0; (!j && i <= j) || i < j; i++){
if(!check(i, j, k, w-1)){ //不符合限制条件的,令dp = 0
dp[i][j][k][now^1] = 0;
continue;
}
dp[i][j][k][now] = (dp[i][j][k][now] + dp[i][j][k][now^1])%mod;
dp[i][j][w-1][now] = (dp[i][j][w-1][now] + dp[i][j][k][now^1])%mod;
dp[i][k][w-1][now] = (dp[i][k][w-1][now] + dp[i][j][k][now^1])%mod;
dp[j][k][w-1][now] = (dp[j][k][w-1][now] + dp[i][j][k][now^1])%mod;
}
}
}
now ^= 1;
}
now ^= 1; //这边不要漏了
for(int k = 0; k < n;k++){
for(int j = 0; (!k && j <= k) || j < k; j++){
for(int i = 0; (!j && i <= j) || i < j; i++){
if(check(i, j, k, n)) //这边要判断一下是否符合限制条件
ans = (ans + dp[i][j][k][now])%mod;
}
}
}
printf("%lld\n", ans);
}
return 0;
}

HDU - 6578 Blank DP + 滚动数组的更多相关文章

  1. hdu 4576(概率dp+滚动数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4576 思路:由于每次从某一位置到达另一位置的概率为0.5,因此我们用dp[i][j]表示第i次操作落在 ...

  2. HDU 1024 Max Sum Plus Plus --- dp+滚动数组

    HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值, ...

  3. HDU 5119 Happy Matt Friends (背包DP + 滚动数组)

    题目链接:HDU 5119 Problem Description Matt has N friends. They are playing a game together. Each of Matt ...

  4. POJ 3666 Making the Grade (DP滚动数组)

    题意:农夫约翰想修一条尽量平缓的路,路的每一段海拔是A[i],修理后是B[i],花费|A[i] – B[i]|,求最小花费.(数据有问题,代码只是单调递增的情况) #include <stdio ...

  5. USACO 2009 Open Grazing2 /// DP+滚动数组oj26223

    题目大意: 输入n,s:n头牛 s个栅栏 输入n头牛的初始位置 改变他们的位置,满足 1.第一头与最后一头的距离尽量大 2.相邻两头牛之间的距离尽量满足 d=(s-1)/(n-1),偏差不超过1 3. ...

  6. hdu 1513 && 1159 poj Palindrome (dp, 滚动数组, LCS)

    题目 以前做过的一道题, 今天又加了一种方法 整理了一下..... 题意:给出一个字符串,问要将这个字符串变成回文串要添加最少几个字符. 方法一: 将该字符串与其反转求一次LCS,然后所求就是n减去 ...

  7. hdu 4576 (简单dp+滚动数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4576 题意:给出1~n的环,m个操作,每次能顺时针或逆时针走w步,询问最后在l~r这段区间内概率.(1 ...

  8. HDU 5617 Jam's maze dp+滚动数组

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5617 bc(中文):http://bestcoder.hdu.edu.cn/contest ...

  9. HDU 6199 DP 滚动数组

    强行卡内存 这题在CF上好像有道极相似的题 可以想到状态设计为dp[f][i][k]表示f在取完i-1时,此时可以取k个或k+1个的状态下的最大值.之前以为n是1e5,自己想不到怎么设计状态真的辣鸡, ...

随机推荐

  1. 匿名函数及paramiko模块

    1.匿名函数 随着程序代码的不断增加,起名字其实也是非常困难的一件事 一些简单的功能完全没必要用def函数,匿名函数足矣 def test(x,y): return x+y res = test(1, ...

  2. vim加脚本注释和文本加密

    vim /etc/vimrc 一.李导版本 autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" fun ...

  3. 63 (OC)* NSAutoreleasePool 自动释放池

    目录 0:ARC 1: 自动释放池 2:NSAutoreleasePool实现原理 3:autorelease 方法 4: Runloop和Autorelease的关系 5: Using Autore ...

  4. RSTP基础配置

    本实验模拟公司网络场景.S3和S4是接入层交换机,负责用户的接入,S1和S2是汇聚层交换机,四台交换机组成一个环形网络.为了防止网络中出现环路,产生网络风暴,所有交换机上都需要运生成树协议.同时为了加 ...

  5. C++ vector、list和deque的区别 (整理)

    1.vector数据结构 vector和数组类似,拥有一段连续的内存空间,并且起始地址不变.因此能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内 ...

  6. [知乎]自己真是Know Nothing 历史上有哪些细思恐极的事件?

    作者:敖让链接:https://www.zhihu.com/question/38374479/answer/652432284来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  7. restful风格详解

    一.概念 RESTful架构,就是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. REST这个词,是Roy Thomas Fielding在他 ...

  8. Intellij IDEA奇巧妙计(不停更新)

    1,在pom.xml文件中,Ctrl+Shift+Alt+U打开Manven依赖视图 2,Alt+7 查看类里面方法,变量等结构 3, Shift+Esc 收缩编译提示框 4, ctrl+r 替换本页 ...

  9. 环境变量和Path环境变量

    环境变量 百度百科下的定义 一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等. 环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所 ...

  10. mongodb连接警告修复

    问题 Node.js中mongoose模块连接MongoDB数据库时提示(node:12580) DeprecationWarning: current URL string parser is de ...