HDU 1565 方格取数(1) (状态压缩DP)

HDU 1565 方格取数(1) (状态压缩DP)

ACM

题目地址:

HDU 1565 方格取数(1)

题意:

中文。

分析:

dp[i][j]表示前i行状态j的最优解。

先预处理出符合条件的数,17000+个(n在20以内)。

不过感觉复杂度挺高的会T,但是却能A。

这题的正解应该是最小割,回头补下。

代码:

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        1565_dp.cpp
*  Create Date: 2014-09-19 23:30:19
*  Descripton:  dp
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;

const int N = 1<<21;

int n, st[N], stn;
int dp[2][N];
int ans, g[25][25];

void pre() {
	repf (i, 0, (1<<20)) {
		if (i & (i<<1))
			continue;
		else
			st[stn++] = i;
	}
}

void solve() {
	if (n == 0) {
		cout << 0 << endl;
		return;
	}
	int tot = 1<<n;
	ans = 0;
	// first line
	for (int i = 0; st[i] < tot; i++) {
		dp[0][i] = 0;
		repf (j, 0, n - 1)
			if (st[i]&(1<<j))
				dp[0][i] += g[0][j];
		ans = max(ans, dp[0][i]);
	}
	// 2~n line
	repf (i, 1, n - 1) {
		for (int j = 0; st[j] < tot; j++) {
			int tmp = 0;
			dp[i&1][j] = 0;
			// can get tmp value
			repf (k, 0, n - 1) {
				if (st[j]&(1<<k))
					tmp += g[i][k];
			}
			for (int k = 0; st[k] < tot; k++) {
				if (!(st[j]&st[k]))
					dp[i&1][j] = max(dp[i&1][j], tmp + dp[!(i&1)][k]);
			}
			ans = max(ans, dp[i&1][j]);
		}
	}
	cout << ans << endl;
	return;
}

int main() {
	ios_base::sync_with_stdio(0);
	pre();
	while (cin >> n) {
		repf (i, 0, n - 1) repf (j, 0, n - 1)
			cin >> g[i][j];
		solve();
	}
	return 0;
}
时间: 2024-10-24 11:55:20

HDU 1565 方格取数(1) (状态压缩DP)的相关文章

hdu 1565 方格取数(1) (状态压缩+dp)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5589    Accepted Submission(s): 2123 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

HDU 1565 方格取数(1)(状压dp)

感觉这道题目的数据比较水啊,程序的时间复杂度为1711^2*20竟然也可以过掉....其他的就是状压了啊,注意需要滚动一下啊.... 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5701    Accepted Submission(s): 2159 Problem Description 给你一个n*n的格子的棋

hdu 1565 方格取数(1)

这个题网上很多人都说用状态压缩dp来做,我就是觉得状态压缩dp有点那么理解不上啊,不过如果这个题吧相邻的两个格子连起来,那不就是求最大权独立点集吗?奋战了三天,我的第一道最大流题目终于写出来了,高兴啊! #include<map> #include<set> #include<stack> #include<queue> #include<cmath> #include<vector> #include<cstdio> #

hdu 1565 方格取数(2)(网络流之最大点权独立集)

题目链接:hdu 1565 方格取数(2) 题意: 有一个n*m的方格,每个方格有一个数,现在让你选一些数.使得和最大. 选的数不能有相邻的. 题解: 我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有: 最大点权独立集 + 最小点权覆盖集 = 总点权和, 这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图, 1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一

网络流 [HDU 1565] 方格取数(1)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5961    Accepted Submission(s): 2268 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数

HDU 1565 方格取数(1) (状态压缩 DP)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5779    Accepted Submission(s): 2194 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

hdu 2167 方格取数 【状压dp】(经典)

<题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数字周围8个点都不能取,问:取得数字的最大和为多少? 解题分析: 由于对每一个数,有选和不选两种可能,分别对应状态压缩中的1和0,且 n<=15,1<<15不是非常大,因此就可以非常自然的想到状态压缩. 此题要与普通的状压dp不同的是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,

HDU 1565 方格取数(1)(状压DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1565 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20) Output 对于每个测试实例,输出可能取得的最大的和 Sample Input 3 75

HDU - 1565 方格取数(1) (DP)

Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20) Output 对于每个测试实例,输出可能取得的最大的和 Sample Input 3 75 15 21 75 15 28 34 70 5 Sample Output 188 思路:用dp[i][j]表示到i行时下