思路:深度搜索复杂度N!过不了。考虑动态规划:将已经选择的列记为1,未选择表示0,二进制压缩,例如110,就表示选择了第1列和第2列。

d(i, t)表示当前已经匹配了i行,选择了t这些列。状态转移:

for(int i = 0; i < n; ++i) {
		int x = 1 << i;
		if(x & val) d = max(d, like[row][i] + dfs(row+1, val - x, k-1));
	}

此时总的状态数就是1<<n,相比N!是极大的优化,减少了很多重复情况的搜索。

用记忆化搜索,代码很好写。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 13 + 5;
int like[maxn][maxn], dp[maxn][1<<13];
int n, ans;
int dfs(int row, int val, int k) { //row表示行,k表示当前选择了多少列
	if(dp[row][val] != -1) return dp[row][val];
	int &d = dp[row][val];
	if(k == 1) { //边界
		for(int i = 0; i < n; ++i) {
			int x = 1 << i;
			if(x & val) return d = like[row][i];
		}
	}
	for(int i = 0; i < n; ++i) {
		int x = 1 << i;
		if(x & val) d = max(d, like[row][i] + dfs(row+1, val - x, k-1));
	}
	return d;
}
int main() {
	while(scanf("%d", &n) == 1) {
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j) {
				scanf("%d", &like[i][j]);
			}
		memset(dp, -1, sizeof(dp));
		int start = (1<<n)-1;
		printf("%d\n", dfs(0, start, n));
	}
	return 0;
}

如有不当之处欢迎指出!

算法提高 金陵十三钗 状压DP的更多相关文章

  1. 计蒜客 31436 - 提高水平 - [状压DP]

    题目链接:https://nanti.jisuanke.com/t/31436 作为一名车手,为了提高自身的姿势水平,平时的练习是必不可少的.小 J 每天的训练包含 $N$ 个训练项目,他会按照某个顺 ...

  2. 「算法笔记」状压 DP

    一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...

  3. 【算法系列学习】状压dp [kuangbin带你飞]专题十二 基础DP1 D - Doing Homework

    https://vjudge.net/contest/68966#problem/D http://blog.csdn.net/u010489389/article/details/19218795 ...

  4. 算法复习——状压dp

    状压dp的核心在于,当我们不能通过表现单一的对象的状态来达到dp的最优子结构和无后效性原则时,我们可能保存多个元素的有关信息··这时候利用2进制的01来表示每个元素相关状态并将其压缩成2进制数就可以达 ...

  5. 【洛谷5492】[PKUWC2018] 随机算法(状压DP)

    点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...

  6. 算法笔记-状压dp

    状压dp 就是把状态压缩的dp 这样还是一种暴力但相对于纯暴力还是优雅的多. 实际上dp就是经过优化的暴力罢了 首先要了解位运算 给个链接吧 [https://blog.csdn.net/u01337 ...

  7. loj2540 「PKUWC2018」随机算法 【状压dp】

    题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...

  8. NOIP2016提高A组 A题 礼物—概率状压dp

    题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有n种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种礼物的喜悦值不能重复获得). 每次,店员会 ...

  9. 有关状压DP

    [以下内容仅为本人在学习中的所感所想,本人水平有限目前尚处学习阶段,如有错误及不妥之处还请各位大佬指正,请谅解,谢谢!] 引言 动态规划虽然已经是对暴力算法的优化,但在某些比较特别的情况下,可以通过一 ...

随机推荐

  1. xml格式字符串转为Map

    import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom ...

  2. linkin大话数据结构--List

    List:Collection子接口 List是有序的集合,集合中每个元素都有对应的顺序序列.List集合可使用重复元素,可以通过索引来访问指定位置的集合元素(顺序索引从0开始),List集合默认按元 ...

  3. C#高性能大容量SOCKET并发(八):通讯协议

    协议种类 开发Socket程序有两种协议类型,一种是用文本描述的,类似HTTP协议,定义字符集,好处是兼容性和调试方便,缺点是解析文本会损耗一些性能:一种是用Code加结构体,定义字节顺序,好处是性能 ...

  4. 新awk整理

    总感觉上一篇awk的总结几乎是照着man翻译过来的,惨不忍睹 无意间在互联网上有找到了宝贵的资料 感觉整理的很好,想着照着这个来重新写下,对照新的man更新下吧,只是总是在改变的 一.awk简介二.a ...

  5. msyql多软件连接

    菜鸟一枚 使用mysql删除数据库时,习惯性使用navicat,由于使用的是sqlyog备份的,就用sqlyog恢复数据库,结果总是报错. 用同事电脑没有问题,后来发现是用了不同的软件,导致数据库数据 ...

  6. struts2.xml的配置问题

    1.<package namespace="/"></package> namespace决定访问action的路径: 如果省略,将代表任意路径: 2.&l ...

  7. Node.js:上传文件,服务端如何获取文件上传进度

    内容概述 multer是常用的Express文件上传中间件.服务端如何获取文件上传的进度,是使用的过程中,很常见的一个问题.在SF上也有同学问了类似问题<nodejs multer有没有查看文件 ...

  8. 字段的参数 -- Django从入门到精通系列教程

    该系列教程系个人原创,并完整发布在个人官网刘江的博客和教程 所有转载本文者,需在顶部显著位置注明原作者及www.liujiangblog.com官网地址. Python及Django学习QQ群:453 ...

  9. java 多维数组遍历

    java 多维数组遍历的顺序的性能问题 ps:下图为java多维数组内存分布原理.出自:http://math.hws.edu/javanotes/c7/two-dimensional-array.p ...

  10. js中的语句

    java语句与js的语句一样.1.判断if else/switch <script type=text/javascript> function fun1(){ var num = 10; ...