2019HDU多校第一场1001 BLANK (DP)(HDU6578)
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)的更多相关文章
- HDU6578 2019HDU多校训练赛第一场 1001 (dp)
HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...
- 2019HDU多校第一场 BLANK DP
题意:有四种数字,现在有若干个限制条件:每个区间中不同的数字种类必须是多少种,问合法的方案数. 思路: 定义 dp[i][j][k][t] 代表填完前 t 个位置后,{0,1,2,3} 这 4 个数字 ...
- [2019HDU多校第一场][HDU 6578][A. Blank]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题目大意:长度为\(n\)的数组要求分别填入\(\{0,1,2,3\}\)四个数中的任意一个,有 ...
- HDU6298 Maximum Multiple (多校第一场1001)
Maximum Multiple Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 2019牛客多校第一场 E-ABBA(dp)
ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...
- 2019牛客多校第一场E ABBA dp
ABBA dp 题意 给出2(N+M)个AB字符,问能构造出N个AB子序列和M个BA子序列组成的2*(n+m)的序列种类有多少 思路 碰到计数构造类的题目,首先要去找到判断合法性的条件,即什么情况下合 ...
- 2018牛客多校第一场 E-Removal【dp】
题目链接:戳这里 转自:戳这里 题意:长度为n的序列,删掉m个数字后有多少种不同的序列.n<=10^5,m<=10. 题解:dp[i][j]表示加入第i个数字后,总共删掉j个数字时,有多少 ...
- [2019HDU多校第一场][HDU 6580][C. Milk]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6580 题目大意:\(n\times m\)大小的方格上有\(k\)瓶水,喝完每瓶水都需要一定的时间.初 ...
- [2019HDU多校第一场][HDU 6584][G. Meteor]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6584 题目大意:求所有满足\(0<\frac{p}{q}\leq1, gcd(p,q)=1,p\ ...
随机推荐
- node常用模块汇总
node常用模块汇总: 点击插件名字,查看使用文档 npm常用模块汇总 node常用模块汇总 gulp常用插件汇总 mkdirp:在node.js中像mkdir -p一样递归创建目录及其子目录
- vs2008 asp.net “无法连接到ASP.NET Development server”
这是因为该网站启动ASP.NET Development server时使用的端口被占用而导致的. 解决方法: 1.在“解决方案资源管理器”中选中网站项目名称,然后切换到“属性”窗口 2.在“属性”窗 ...
- react-react中的css+评论组件
一个小案例,巩固有状态组件和无状态组件的使用 通过for循环生成多个组件 数据: CommentList = [ { user: '张三', content: '哈哈,沙发' }, { user: ' ...
- Babel 7 主要改变
1.不支持Node:0.10,0.12,4,5版本 2.更换命名-@babel/xxx 3.移除以年份命名的presets,统一更换成@babel/preset-env 4.移除 ’Stage‘ pr ...
- Wannafly Camp 2020 Day 6F 图与三角形 - 图论
把黑边视为无边,那么答案之和每个点的度数有关 #include <bits/stdc++.h> using namespace std; #define int long long int ...
- ORA-12638: 身份证明检索失败
PLSQL 连接Oracle时提示 “ORA-12638: 身份证明检索失败” 错误, 但是开发IDE可以正常连接,DataGrid 可以正常连接,所以确定是本地设置问题. 网上搜了一下,说是因为Or ...
- 在vue中使用elementUI饿了么框架使用el-tabs,切换Tab如何实现实时加载,以及el-table表格使用总结
当我们在开发中遇到tab切换,这时候用el的el-tabs感觉很方便 但当我在把代码都写完后,发现一个问题就是页面打开时 虽然我们只能看见当前一个tab页,但是vue会帮你把你写的所有tab页的内容都 ...
- SpringBoot学习- 5、整合Redis
SpringBoot学习足迹 SpringBoot项目中访问Redis主要有两种方式:JedisPool和RedisTemplate,本文使用JedisPool 1.pom.xml添加dependen ...
- 前端Css学习
CSS 称为层叠样式表 css样式引入方式 第一种 head标签中引入 <style> /* 选择器{css属性名称:属性值;css属性名称:属性值;} */ div{ /* css注释 ...
- ACWing 238 银河英雄传说
最近带权并查集这块比较薄弱,直接看食物链看不懂,就老实一步步来了. 有一个划分为N列的星际战场,各列依次编号为1,2,…,N. 有N艘战舰,也依次编号为1,2,…,N,其中第i号战舰处于第i列. 有T ...