12380网站建设情况说明手机兼职群
12380网站建设情况说明,手机兼职群,网站建设价格标准报价,如何设计微商城网站建设今天更新一道不错的状态压缩DP题#xff0c;顺带总结一下状态压缩DP。 摘要#xff1a; Part1 浅谈状态压缩DP的理解 Part2 浅谈对状态机DP的理解 Part3 关于状态压缩DP的1道例题 Part1 状态压缩DP 1、状态压缩DP#xff1a; 事物的状态可能包含多个特征#xff0c;…今天更新一道不错的状态压缩DP题顺带总结一下状态压缩DP。 摘要 Part1 浅谈状态压缩DP的理解 Part2 浅谈对状态机DP的理解 Part3 关于状态压缩DP的1道例题 Part1 状态压缩DP 1、状态压缩DP 事物的状态可能包含多个特征但是事物的状态之间却可以互相转移此时我们引入状态压缩DP将事物的复杂的状态用一个数字来替代此时事物的状态可以用数组的某个位置表示从而可以进行状态的转移。2、常见的状态表示 (1) 用10进制数字本身表示状态比如表示当前状态%某个数字的余数等等这里举一个例子。 (2) 用10进制内蕴含的二进制位表示状态, 01, 表示了每个位置上的两种状态它既可以表示是否存在也可以表示数量的奇偶性。 (3) 用10进制内蕴含的K进制(除了10进制和2进制外的其它进制)表示状态这种题我没见过但是基于上面我们很容易可以推广。3、什么时候我们可以用: 首先是在你的状态表示基础上整体的转移图是一个拓扑图也就是可以通过递推得来并且时间空间可以过得去此时我们就可以用状态压缩DP。 Part2 状态机DP
我在之前写过一篇关于状态机DP的文章里面有详细的理论和几道很好的例题
http://t.csdnimg.cn/POtFs Part3 例题: 小红的回文数
题目链接E-小红的回文数_牛客周赛 Round 32 (nowcoder.com) (1)题意 小红定义一个整数是“好数”当且仅当该整数通过重排之后可以形成回文数。可以包含前导零现在小红拿到了一个正整数x小红想截取一段连续区间得到好数她想知道有多少种不同的方案 (2)题解 暴力显然会超时必定需要n * n 的复杂度此时我们不妨考虑一下DP, 我们此时从左到右去考虑这个数我们考虑每个以第i位数结尾的情况最后答案就是累加后的值我们此时考虑一下以第i位数结尾的区间我们发现对于一个数字而言每位的数字只能是0-9的数字之一我们不妨用10个二进制位表示每一种数字的数量%2是多少这样我们就可以通过统计1的个数判断有几个奇数如果要构造一个回文串显然只能由一个或者0个奇数的位。状态转移方程表示以第i位数结尾的数字区间且0-9各个的数字情况是state的方案数并且对于每个位单独一位的情况也要考虑所以状态转移代码是 vectorvectorint dp(n 1, vectorint((1 10) 2)); dp[0][0] 1; for(int i 1; i n; i ) {for(int j 0; j (1 10); j ) {int k j ^ (1 (s[i - 1] - 0));dp[i][k] dp[i - 1][j]; }if(i 2) dp[i][1 (s[i - 1] - 0)] ; } 你以为事情结束了吗这是一道比较毒瘤的题它会卡你的空间在此基础上我们需要引入滚动数组优化优化掉一维的空间。 此时的转移代码是 dp[0] 1; long long res 0; for(int i 1; i n; i ) {memset(usdp, 0, sizeof usdp); for(int j 0; j 1 10; j ) usdp[j ^ (1 (s[i - 1] - 0))] dp[j];if(i 2) usdp[1 (s[i - 1] - 0)] ; for(int j 0; j 1 10; j ) {cnt 0; for(int c 0; c 9; c ) if(j c 1) cnt; if(cnt 1) res usdp[j]; dp[j] usdp[j]; }}cout res endl; (3) 代码 C : 滚动数组优化: #include bits/stdc.h
// #define int long long
#define lowbit(x) (x-x)
using namespace std;
const int N 1e5 2;
const int inf 0x3f3f3f3f;
int n, cnt;
long long dp[2025], usdp[2025];
// int a[N];
void solve() {string s; cin s; n s.size();cnt 0;
// for(int i 1; i n; i ) a[i] s[i - 1] - 0; dp[0] 1; long long res 0; for(int i 1; i n; i ) {memset(usdp, 0, sizeof usdp); for(int j 0; j 1 10; j ) usdp[j ^ (1 (s[i - 1] - 0))] dp[j];if(i 2) usdp[1 (s[i - 1] - 0)] ; for(int j 0; j 1 10; j ) {cnt 0; for(int c 0; c 9; c ) if(j c 1) cnt; if(cnt 1) res usdp[j]; dp[j] usdp[j]; }}cout res endl; }
int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int ts 1;
// cin ts; while(ts -- ) solve(); return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/87628.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!