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. 安装DHCP到CentOS(YUM)

    运行环境 系统版本:CentOS Linux release 7.3.1611 (Core) 软件版本:DHCP-x 硬件要求:无 安装过程 1.安装YUM源,由EPEL提供 [root@localh ...

  2. SDN-数据控制分离

    严格来说,控制面与数据面分离并不是SDN的专利.从一个chassis角度看,传统路由器其实控制面和转发面也是分离的.Route-enginee和line card分别负责控制面板和转发面.但是传统网络 ...

  3. oracle Insert 一次插入多条记录

    oracle Insert 一次插入多条记录有两种方法: 1)Insert All Into table_name values ... insert all into table_name valu ...

  4. AI机器人最高等级

    AI机器人最高等级 题目描述 在小朱朱的游戏世界里,有n个AI机器人. 他们相互之间可以进行PK,胜方存活且升一级,负方直接淘汰. 高等级AI必定战胜低等级AI,同等级AI的PK结果必定一胜一负,且规 ...

  5. HashMap源码刨析(面试必看)

    目录 1.Hash的计算规则? 2.HashMap是怎么形成环形链表的(即为什么不是线程安全)?(1.7中的问题) 3.JDK1.7和1.8的HashMap不同点? 4.HashMap和HashTab ...

  6. 安装oracle client及配置

    一.下载oracle client 下载地址:https://www.oracle.com/technetwork/database/enterprise-edition/downloads/1120 ...

  7. php redis使用

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

  8. display: inline-block 布局

    三个元素display: inline-block; 布局 ,其中一个元素中存在其他元素也用了display: inline-block; 无法垂直居中,将这个元素设置为display: inline ...

  9. 一步步教你如何在Ubuntu虚拟机中安装QEMU并模拟模拟arm 开发环境(一)uImage u-boot(转)

    初次接触qemu是因为工作的需要,有时候下了班,可能需要在家研究一些东西,因为博主用到arm环境,这时候博主比较小气,不愿花钱买开发板,当然博主在这里给大家的建议是,如果要真正学懂arm构架的相关知识 ...

  10. LINUX使用SSH远程终端时,如何将运行时间长的程序在后台挂起,下次SSH登陆时继续使用同一个SHELL?

    我在某个平台上购买了一个云服务器,LINUX操作系统无图形化界面,硬盘空间较小.虽然在平台上可以通过其自带网页版VNC界面登陆SHELL进而操控云主机,但是每次需要操控都得打开网页登陆进平台,然后再进 ...