随笔分类 -  状态压缩

摘要:题意:给定一个合法的八皇后棋盘,现在给定1-10个骑士,问这些骑士不能够相互攻击的拜访方式有多少种。分析:一开始想着搜索写,发现该题和八皇后不同,八皇后每一行只能够摆放一个棋子,因此搜索收敛的很快,但是骑士的话就需要对每一个格子分两种情况进行,情况非常的多,搜索肯定是会超时的。状态压缩DP就是另外一个思路的,理论上时间复杂度是8*n*2^24,但是由于限制比较多,也就能够解决了。设dp[i][j][p][q]表示第i-1行压缩后的状态是p,第i行压缩后的状态为q,且之前一共使用了j个骑士的方案数。按照题意递推即可。#include #include #include #include #inc 阅读全文
posted @ 2013-11-09 20:36 沐阳 阅读(819) 评论(0) 推荐(0) 编辑
摘要:题意:给定一个网格图,图中有一些点要求全部走到,问最少的花费是多少,从任意边界进入,任意边界出去,如果不能够全部走到,输出0。解法:一次spfa从边界上的所有点出发,计算到K个宝藏的最短路,然后计算出任意两个宝藏之间的最短路,最后状态压缩枚举即可。代码如下:#include <cstdlib>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;// 记得要带走全部的物品 const int INF = 阅读全文
posted @ 2013-06-07 15:36 沐阳 阅读(510) 评论(0) 推荐(0) 编辑
摘要:题意:一个裸的枚举题,告诉你M个点,问这M个点能否覆盖其他非M点。做的时候时间复杂度计算错误。。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>using namespace std;int N, M;int r[15];int x[15], y[15];char mp[55][55];char tp[55][55];const int INF = 0x3f3f3f3f;bool judge 阅读全文
posted @ 2013-05-29 21:29 沐阳 阅读(237) 评论(0) 推荐(0) 编辑
摘要:题意:给定一系列的数码管,这些数码管由3*3的图形构成,相邻的两个数码管紧挨着的一列是重叠的,现在问一共有多少种可能的情况。解法:将每个数字的可能的显示结果(能亮的地方假设都可以亮)保留起来,然后一个一个数码枚举,一个地方要注意就是相邻意味前面一个数码占用了某一个亮线,那么后面这个数码可以选择是否占用该亮线,而如果前面没用占用该亮线则后面的数码必须占用。使用f[i][j]表示到第i个字符,占用相邻列情况为j时的方案数。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include < 阅读全文
posted @ 2013-05-07 23:06 沐阳 阅读(421) 评论(0) 推荐(0) 编辑
摘要:题意:给定一个图,求出两点之间的最短路,但是这个最短路是在一条路径上的某条最贵的边能够忽略的情况下的最小值。分析:直接求出一条最短路再减去这条最短路中的最大值的做法是错误的。例如:如果A-B存在一条(2, 2, 2, 2, 2)的总长为10的路,减去最大值之后是8,存在另外一条路径(1, 8, 2),总长为11,但是减去最大的8之后就是3了,因此这里要用到动态规划来解。设dp[0][i][j]表示从i到j不使用免费权的最短路径,dp[1][i][j]表示使用免费权的最短路径,则有动态方程:dp[1][i][j] = min(dp[0][i][k] + dp[1][k][j], dp[1][i] 阅读全文
posted @ 2013-03-10 09:48 沐阳 阅读(621) 评论(0) 推荐(0) 编辑
摘要:题意:给定一个网络,每条线路都同时有几个公式拥有,现在问某两点之间哪些公司通过自己拥有的路径单独联通。分析:问题开起来是给定了多个图,对他们分别求一个连通性,但是这里把多个图压缩到一个int型数字内,因为这里只是简简单单求一个连通性,使用位运算非常高效。代码如下:#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;int G[205][205];int N;void floyd() { for (int k = 1; 阅读全文
posted @ 2013-03-09 20:48 沐阳 阅读(228) 评论(0) 推荐(0) 编辑
摘要:由于递推的时候依赖于三个连续层的关系.一开始想着直接三重for循环,但是这里有个问题就是上一层的0位置上包括着上上层是0和1两种可能,而后者又对当前行有约束,因此该方法不行.当然有一个办法就是增加状态数,让状态能够表示是从1还是从0转移过来的.(这题有个解法是采用多进制的状态压缩). 网上瞄了别人的一眼解题报告. 瞬间顿悟,竟然三层之间发生关系,那么就直接把连续的两层记录起来,虽然说空间上不及多进制优美. 但是却能够去描述这些个问题.代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#incl 阅读全文
posted @ 2013-01-15 21:33 沐阳 阅读(464) 评论(0) 推荐(0) 编辑
摘要:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>#define MOD 100000000using namespace std;/*题意:给定一个矩阵,这个矩阵表示了一块土地,给定的数据只有0,1, 表示土地肥沃与否. 其中0代表不肥沃,1代表肥沃. 不肥沃的地方是不能够种植玉米的,还有一个约束就是 不能够在相邻的1种植玉米. 现在问一共有多少种种植方式. 解法:明显的状态压缩题,先dfs出一行的非 阅读全文
posted @ 2013-01-15 17:29 沐阳 阅读(436) 评论(0) 推荐(0) 编辑
摘要:该题解题过程非常优美,通过位操作来维护一个可选字符集合.并且完成求并集和交集.详见代码:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;/*花了大半个小时看懂了这题题意:给定N个字符串,N为2的幂,每个字符串长度为L,这N个字符串是一棵完全二叉树的叶子节点,现在问树的内部在同样要填入长度为L的字符串的情况下,最少的花费是多少,根节点是什么. 花费是这样计算的:一 阅读全文
posted @ 2013-01-11 20:34 沐阳 阅读(753) 评论(0) 推荐(1) 编辑
摘要:http://www.cnblogs.com/Lyush/archive/2012/03/23/2413160.html曾几何时,也写过这一题,那是刚跟着做什么状态压缩dp的时候,1844MS过的,现在终于0MS了.这次的做法有点不一样,首先原来的两个指数级的for循环嵌套,变成一个指数级嵌套一个合法状态的个数,状态的含义也发生了改变,由原来的0,1只表示覆盖,变成了0表示横向覆盖,1表示了纵向覆盖,0和1保留了更多的信息,最后采用了一种退化机制来确保一列中不出现连续的奇数个1,即如果出现了偶数个1的话,那么最后这个1就等价于0,表示下一行下的这一列为0为1均可.那么上一层的合法状态由于发生退 阅读全文
posted @ 2013-01-08 12:37 沐阳 阅读(581) 评论(0) 推荐(0) 编辑
摘要:给定两个数,这两个数的长度都不超过6位数,然后求后一个数被怎样的分割能使得其和值最接近前一个数,其实这个问题就相当于在后一个数中进行插板而已。通过状态压缩来枚举隔板即可。代码如下:#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <string>#include <map>#include <queue># 阅读全文
posted @ 2012-09-12 07:13 沐阳 阅读(242) 评论(0) 推荐(0) 编辑
摘要:将所有括号都找出来,枚举所有的可能,再用strcmp排下序就可以了。标程用到的方法更好,直接标记每个括号属于哪一个括号组,然后直接解压状态即可。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;char s[210], rec[1050][210];int stack[15], top, length, cnt;struct Parentheses{ int l, r;}P[15];void init( 阅读全文
posted @ 2012-08-01 09:18 沐阳 阅读(265) 评论(0) 推荐(0) 编辑
摘要:由于只有最多16种组合情况,所以就直接暴力枚举求解。这里题目有个要求就是按照字典序相对较小的输出规则输出,那么我们可以想到在兴趣数相同的情况下要不要去更新最优值,这就牵涉到我们刚开始的时候求解出来的解是否一定是字典序最小的,或则最后求解出来的解就是字典序最小的,我是采用压缩后的二进制数的最高位代表最小的兴趣,所以从最高位通过自减操作能够保证每次得到的该兴趣数的第一个解都是字典序最小的。#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using nam 阅读全文
posted @ 2012-08-01 09:02 沐阳 阅读(325) 评论(0) 推荐(0) 编辑
摘要:这题简单说就是求矩形的面积并,线段树?只有20个矩形,我们可以用容斥来做。但是这个有个比较麻烦的地方就是要求出任意组合情况下的面积并,试过几次每次进行求解的写法都一一超时了。这里选择在dfs的时候直接枚举题目将询问的状态,只要当前状态是其子集的话,就直接加到上面。最后M次询问就能够在O(1)的时间内完成了。296MS水过了。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#define INF 10000using namespace st 阅读全文
posted @ 2012-07-28 20:26 沐阳 阅读(727) 评论(0) 推荐(0) 编辑
摘要:这题用贪心是很容易过的,直接先杀死对方单位时间输出较高的对象。这题的动态规划解是将N个敌人压缩到一个int数里面,dp[j] 表示在剩余了j这个数里面所蕴含的敌人的情况下的最大扣血量。dp方程为 dp[s] = min( dp[s - {bit}] + sumdps[s] * h[bit] ) 其中bit枚举每一位。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;int dp[1200000], N, 阅读全文
posted @ 2012-07-27 00:42 沐阳 阅读(305) 评论(0) 推荐(0) 编辑
摘要:做法与1753相似。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define START 0#define END 65535using namespace std;char G[6][6];int status, cpy, how[20], path[20], times;void pre(){ how[1] = 4383, how[2] =8751, how[3] = 17487, how[4] = 34959, how[5] = 阅读全文
posted @ 2012-06-28 12:06 沐阳 阅读(265) 评论(0) 推荐(0) 编辑
摘要:刚开始做这题时总是在想应该用何种的策略来进行翻装,最后还是没有想出来~~~ 这题过的代码的思路是用在考虑到每个点被翻装的次数只有0次或者是1次,所以对于16个点就只有2^16中请况了。再运用位运算将状态压缩到一个32位的整型当中,使用异或运算替代普通的运算。用dfs生成排列数。 代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#define START 0#define END 65535using namespace std;char G 阅读全文
posted @ 2012-06-28 11:12 沐阳 阅读(258) 评论(0) 推荐(0) 编辑
摘要:还记得杭电的“骨牌铺方格”吗,这题可以说是它的强化板了。但是思路是一样的,就是通过得到前面的解来递推后面的结果。由于是一个较大的平面,较之杭电那题在行数和列数上都有了较多的组合情况,因此状态压缩有了用武之地。这题的一个难点就是如何用0,1来表示摆放的规律,参看别人的想法后,找到的这种方法虽然时间开销相对大了点,但是思路非常好理解。对于每一个格子,只有0,1两种状态,0代表没有放置,1代表放置。对于每一行的状态,1的含义会因为上一行的对应项而不同,如果与之对应的上一行的列为0的话,那么这个1代表这里放置了一个竖直的块,如果上一列是1的话那么两行都必须是横着放置的。2411Accepted328K 阅读全文
posted @ 2012-03-23 09:53 沐阳 阅读(705) 评论(0) 推荐(1) 编辑
摘要:这题相对于前面的little kings 来说简单了一些,没有了步数的限制,dp方程也简洁了不少。只需要考虑当前状态是否与上一个状态冲突即可。代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#define MAXN 20000using namespace std;long long f[25][MAXN];int N, M, map[25][25], s[MAXN];inline long long max(long long &x 阅读全文
posted @ 2012-03-16 15:43 沐阳 阅读(473) 评论(1) 推荐(0) 编辑
摘要:这算是八皇后问题的变种了,普通的组合数学已经很难一下子将他求出来了,除此之外,我们用纯模拟来处理该题。 给定是一个N*N的矩阵,要求在这个图中放置K个点,这些点不能够相邻(包括上下左右以及对角线上的区域),用模拟如何来过这一题呢,那就是要推出动态递归方程,F[i][s][k] 代表第i行处于第s个状态且到目前行共下了k个棋子的总方案数,c[s]代表针对s这个状态有多少个1,有动态方程:F[i][s][k] = sum{ F[i-1][s'][k-c[s]],其中 s 与 s' 为不冲突的方案数 } 该方程的含义为 F[i][s][k] 中剩余的棋子数 k-c[s] 在上一行截止 阅读全文
posted @ 2012-03-15 15:53 沐阳 阅读(564) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示