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\ ...
随机推荐
- stringstream使用小结
1.头文件:#include<sstream> 2.stringstream是C++提供的串流(stream)物件 3.clear()重置流的标志状态:str()清空流的内存缓冲,重复使用 ...
- jmeter测试出现端口占用
原文地址:https://www.cnblogs.com/deepSleeping/p/12067654.html Jmeter测试会出现端口占用情况 这边在这里做个记录,每次都要百度查询,刚好需要整 ...
- ArcMap 发布 ArcGIS Server OGC(WMSServer,MapServer)服务
完整的从ArcMap部署地图到ArcGIS Server 中作为地图服务的过程. 1. 添加图层数据-- 不能添加地图 baseMap 2. 安装ArcGIS Server ,记住登录Manager ...
- C# WPF过渡效果实现(C# WPF Material Design UI: Transitions)
时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...
- AduSkin - UI
追求极致,永臻完美 A Beautiful WPF Control UI 一款简单漂亮的WPF UI,融合部分开源框架的组件,为个人定制的UI,可供学者参考. Nuget 搜索"AduSki ...
- python数据分析学习(2)pandas二维工具DataFrame讲解
目录 二:pandas数据结构介绍 下面继续讲解pandas的第二个工具DataFrame. 二:pandas数据结构介绍 2.DataFarme DataFarme表示的是矩阵的数据表,包含 ...
- 事件分析法学习笔记(ESM)
事件分析法基础学习笔记 1.定义 事件分析法是研究某事件的发生对组织价值的影响以及影响程度. 或者说研究特定事件对组织行为的影响. notes:事件分析法的关键点在于探讨所关注事件在某个时段产生的 ...
- Visual Studio 问题汇总
VS2019 16.3.6 1 JSON 文件没有进行格式化验证 开发时运行正常,部署在IIS中有错误提示. 2 .NET Core 3.0 没有提供中文包 所有注释都是英文的.
- eclipse中配置maven环境
一.配置setting.xml文件 1.首先将下载好的maven打开,打开文件夹,首先就需要对maven安装目录下有个config文件夹,在文件夹下有settings.xml文件.settings里面 ...
- 杭电oj_2047——阿牛的EOF牛肉串(java实现)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2047 思路:先是列出了四个,但是没发现规律,然后开始画递归树,在其中找到了规律,算出递归式为f(n) ...