2019HDU多校第一场1001 BLANK (DP)

题意:构造一个长度为n(n<=10)的序列,其中的值域为{0,1,2,3}存在m个限制条件,表示为 l r x意义为[L,R]区间里最多能有x个不同的数字,计算序列构造方案数

思路

1.首先考虑最暴力的做法,直接dfs暴力构造,碰到区间的右端点就开始判断当前构造是否满足,如果不满足就回溯,很显然,复杂度爆炸O(4^n)

2.考虑怎么优化暴力算法,从(n<=100)不难猜出这是一个dp,考虑这种字符串构造形式的dp,肯定是一位一位有序构造,所以dp肯定是有序地扫一遍,所以进入了如何定义状态的阶段,我们注意到,一个区间里面数的种类的不同,只与当前点分别和最近的{0,1,2,3}的距离有关,如果在限制区间里面则种类+1,反之亦然。所以我们不难想到可以定义出状态dp[i][j][k][t][pos],表示{0,1,2,3}在Pos位置之前离pos最近分别在i,j,k,t,这样我们得出状态转移方程有(分别为填0,1,2,3)

dp[i][j][k][pos][pos]+=dp[i][j][k][t][pos-1]

dp[i][pos][k][t][pos]+=dp[i][j][k][t][pos-1]

dp[i][pos][k][t][pos]+=dp[i][j][k][t][pos-1]

dp[pos][j][k][t][pos]+=dp[i][j][k][t][pos-1]

我们可以得出,时间复杂度\(O(n^5)\)空间复杂度\(O(n^5)\)两者都不行,所以我们需要考虑如何优化,从状态转移方程中我们可以看到在5维中总有一对pos是相同的,所以这一维可以不用占时间复杂度和空间复杂度,并且可以用数组滚动,所以空间复杂度可以为\(O(n^3)\),时间复杂度为\(O(n^4)\)至此,已经满足题意了

但是我们试图对以上状态转移进行优化时,我们会发现pos到底和哪一位一样?这很难处理。因为pos既代表了一位数的位数又代表了当前位置,这样如何表达呢?我们思考一下,pos相对于i,j,k有什么性质?pos每次都是最大的,同时填{0,1,2,3}我们并不关心他的具体取值,只关系他的分布,所以取什么值都是对称的,例如0,1,2,3如果满足条件,那么3,2,1,0也一定满足条件,所以我们可不可以仅从分布位置的大小关系入手?设置i<j<k<t那么转移就变成了

dp[i][j][pos][now]+=dp[i][j][k][pre]

dp[i][k][pos-1][now]+=dp[i][j][k][pre]

dp[j][k][pos-1][now]+=dp[i][j][k][pre]

dp[i][j][pos-1][now]+=dp[i][j][k][pre]

我们分别解释第一个状态和第二个状态。首先我们可以知道,上一个状态最大的肯定是pos-1也就是当前状态的k=pos-1因为当前位置是pos,第一个状态表示把pos位置填上和k相同的值。而第二个状态表示把pos填上和j相同的值,那么上一个k可以就是pos-1变成了次大值,最大值变成了pos也就是当前填的值。(每个状态里面都隐藏了当前的最大t一定是位置,以此好理解转移)

这样我们就还剩下了限制条件,我们只要把每个限制条件放进以右端点值为key的数组中,每次dp完一个位置后,看满不满足限制条件,不满足就置为0即可,因为状态的良好定义,使得判断极为简单

思考

碰到构造计数类dp的时候,通常是从左到右dp,我们首先考虑如何判断限制条件,再以此设计状态,状态的定义要可以很方便得判断出是否满足限制条件,对于不满足限制条件的状态,我们可以在dp中使dp数组置0来阻止其继续递推。设计状态的时候从最暴力逐渐优化,思路不能乱,不能乱了方寸,否则dp的难度一高,状态一复杂,就会导致心态爆炸,代码写炸。

Reference

https://blog.csdn.net/Ratina/article/details/97237438 顺便%一下这位大佬

#include<bits/stdc++.h>
#include<vector>
#include<algorithm>
using namespace std;
#define pb push_back
#define F first
#define S second
#define mkp make_pair
const int mod=998244353;
const int maxn=100+4;
int dp[maxn][maxn][maxn][2];
vector< pair<pair<int,int>,int> >v[maxn];
int t,n,m;
int ans=0;
int add(int x,int y){
return (1ll*x+y)%mod;
}
int main(){
scanf("%d",&t);
while(t--){
ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
v[i].clear();
for(int i=0;i<m;i++){
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
v[r].pb(mkp(mkp(l,r),x));
} for(int k=0;k<n;k++)
for(int j=0;j<max(1,k);j++)
for(int i=0;i<max(1,j);i++)dp[i][j][k][1]=dp[i][j][k][0]=0;
dp[0][0][0][0]=1; int now=1;
for(int pos=1;pos<=n;pos++){
for(int k=0;k<max(pos-1,1);k++){
for(int j=0;j<max(1,k);j++){
for(int i=0;i<max(1,j);i++){
dp[i][j][k][now]=add(dp[i][j][k][now],dp[i][j][k][now^1]);
dp[i][j][pos-1][now]=add(dp[i][j][pos-1][now],dp[i][j][k][now^1]);
dp[j][k][pos-1][now]=add(dp[j][k][pos-1][now],dp[i][j][k][now^1]);
dp[i][k][pos-1][now]=add(dp[i][k][pos-1][now],dp[i][j][k][now^1]);
dp[i][j][k][now^1]=0; }
}
}
for(int k=0;k<max(pos,1);k++){
for(int j=0;j<max(1,k);j++){
for(int i=0;i<max(1,j);i++){
for(auto&p:v[pos]){
if((i>=p.F.F)+(j>=p.F.F)+(k>=p.F.F)+1!=p.S){
dp[i][j][k][now]=0;
}
} }
}
}
now^=1;
}
for(int k=0;k<max(1,n);k++){
for(int j=0;j<max(1,k);j++){
for(int i=0;i<max(1,j);i++){
ans=add(ans,dp[i][j][k][now^1]);
}
}
}
printf("%d\n",ans); } return 0;
}

2019HDU多校第一场1001 BLANK (DP)(HDU6578)的更多相关文章

  1. HDU6578 2019HDU多校训练赛第一场 1001 (dp)

    HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...

  2. 2019HDU多校第一场 BLANK DP

    题意:有四种数字,现在有若干个限制条件:每个区间中不同的数字种类必须是多少种,问合法的方案数. 思路: 定义 dp[i][j][k][t] 代表填完前 t 个位置后,{0,1,2,3} 这 4 个数字 ...

  3. [2019HDU多校第一场][HDU 6578][A. Blank]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题目大意:长度为\(n\)的数组要求分别填入\(\{0,1,2,3\}\)四个数中的任意一个,有 ...

  4. HDU6298 Maximum Multiple (多校第一场1001)

    Maximum Multiple Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. 2019牛客多校第一场 E-ABBA(dp)

    ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...

  6. 2019牛客多校第一场E ABBA dp

    ABBA dp 题意 给出2(N+M)个AB字符,问能构造出N个AB子序列和M个BA子序列组成的2*(n+m)的序列种类有多少 思路 碰到计数构造类的题目,首先要去找到判断合法性的条件,即什么情况下合 ...

  7. 2018牛客多校第一场 E-Removal【dp】

    题目链接:戳这里 转自:戳这里 题意:长度为n的序列,删掉m个数字后有多少种不同的序列.n<=10^5,m<=10. 题解:dp[i][j]表示加入第i个数字后,总共删掉j个数字时,有多少 ...

  8. [2019HDU多校第一场][HDU 6580][C. Milk]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6580 题目大意:\(n\times m\)大小的方格上有\(k\)瓶水,喝完每瓶水都需要一定的时间.初 ...

  9. [2019HDU多校第一场][HDU 6584][G. Meteor]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6584 题目大意:求所有满足\(0<\frac{p}{q}\leq1, gcd(p,q)=1,p\ ...

随机推荐

  1. Python-Django学习笔记(四)-views的编写以及urls分发器的配置

    MTV中的V表示的是Views,视图函数(或简称视图)只是一个Python函数,它接受Web请求并返回Web响应. 通俗的理解可以理解为后端控制器. (响应可以是网页的HTML内容,重定向,404错误 ...

  2. JavaScript:JSON对象

    一.JSON对象概念 JSON (JavaScript Object Notation)一种简单的数据格式,比xml更轻巧. JSON 是 JavaScript 原生格式,这意味着在 JavaScri ...

  3. phpcms v9 标签调用,函数,sql

    1.截取调用标题长度 {str_cut($r[title],36,'')} 2.格式化时间 调用格式化时间 2011-05-06 11:22:33 {date('Y-m-d H:i:s',$r[inp ...

  4. 1级搭建类113-Oracle 11gR2 SI FS(OEL 6.10)

    Oracle 11g 单实例文件系统搭建(EMDC) EMDC:Database Control 单实例主机.数据库等监控,这东西12c之后没有了 EMGC:Grid Control 单独安装GC软件 ...

  5. 【Linux02】LInux初始入门

    1.LInux操作系统发展与演变 ENIARC: CUP:运算器.控制器.寄存器.缓存 存储器:内存.RAM Input:指令+数据 Output:结果 程序:指令+数据    算法+数据结构 字节是 ...

  6. Docker安装部署es集群

    Docker安装部署es集群:环境准备:已安装docker的centos服务器一台1. 拉取es版本docker pull elasticsearch:5.6.82. 新建文件夹 数据挂载目录 和 配 ...

  7. php redis使用

    访问连接 远程访问 //实例化 $redis=new Redis(); try{ $redis->connect('47.98.55.11','6379'); $redis->auth(' ...

  8. js中变量含(参数、数组)作用域传递问题

    js没有块级作用域(你可以自己闭包或其他方法实现),只有函数级作用域和全局作用域,函数外面的变量函数里面可以找到使用,函数里面的变量外面无法访问到. 写这个是因为ES6中的一个例子开始的.首先看下例子 ...

  9. 根据JSON的值设置radio选中状态

    说明:页面有一组单选按钮radio,现在页面发送请求得到一组json数据,包括radio的值. 需要根据JSON中的值绑定radio的选中状态> <table class="ta ...

  10. Cannot read property 'resolve' of undefined

    可能是node下载的有问题 推荐官网:https://nodejs.org/zh-cn/