HDU1565—方格取数(1)——状压DP
2015-07-30 19:59
281 查看
Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
[b]Input
[/b]
包括多个测试实例,每个测试实例包括一个整数n
和n*n个非负数(n<=20)
[b]Output[/b]
对于每个测试实例,输出可能取得的最大的和
Sample Input
3
75 15 21
75 15 28
34 70 5
Sample Output
188
本题思路::肯定是状态压缩的DP。把每一种可能的状态存放在 mp 数组中,共有tot种状态。用 dp 二维数组记录最大值。其中dp[ i ][ j ]表示到第 i 行 j 状态的最大值。状态转变方程为dp[ i ][ j ] = max(dp[ i ][ j ] , dp[ i-1 ][ k ] + sum[ j ]); 其中dp[ i - 1 ][ k ]表示第 i
- 1 行 k 状态 ,sum 为 i 行 j 状态的总和。详情看代码。
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
[b]Input
[/b]
包括多个测试实例,每个测试实例包括一个整数n
和n*n个非负数(n<=20)
[b]Output[/b]
对于每个测试实例,输出可能取得的最大的和
Sample Input
3
75 15 21
75 15 28
34 70 5
Sample Output
188
本题思路::肯定是状态压缩的DP。把每一种可能的状态存放在 mp 数组中,共有tot种状态。用 dp 二维数组记录最大值。其中dp[ i ][ j ]表示到第 i 行 j 状态的最大值。状态转变方程为dp[ i ][ j ] = max(dp[ i ][ j ] , dp[ i-1 ][ k ] + sum[ j ]); 其中dp[ i - 1 ][ k ]表示第 i
- 1 行 k 状态 ,sum 为 i 行 j 状态的总和。详情看代码。
//这道题的关键在于时间和空间复杂度思路还是比较简单 //第一次::把每一个状态都记录在数组中,超了空间 //第二次::把不可能的状态踢掉,超了时间 //第三次::看了网上的题解,发现可以把当前行,和上一行换位置,节省了大量时间,过掉了 #include <iostream> #include <sstream> #include <ios> #include <iomanip> #include <functional> #include <algorithm> #include <vector> #include <string> #include <list> #include <queue> #include <deque> #include <stack> #include <set> #include <map> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <climits> #include <cctype> using namespace std; #define XINF INT_MAX #define INF 0x3FFFFFFF #define MP(X,Y) make_pair(X,Y) #define PB(X) push_back(X) #define REP(X,N) for(int X=0;X<N;X++) #define REP2(X,L,R) for(int X=L;X<=R;X++) #define DEP(X,R,L) for(int X=R;X>=L;X--) #define CLR(A,X) memset(A,X,sizeof(A)) #define IT iterator typedef long long ll; typedef pair<int,int> PII; typedef vector<PII> VII; typedef vector<int> VI; //const int MAXN = 10010; //#define INF 0x3FFFFFFF /*************************************** *****************头文件***************** ****************************************/ int mp[20000]; //曾经尝试用map,后来发现和数组功能完全相同 int dp[20][20000];//可以进一步改为滚动数组可节省空间 int maps[23][23];//记录值 int main() { int n; while(cin>>n){ memset(dp,0,sizeof(dp)); REP2(i,1,n)//这里从第一行开始记录 REP(j,n) //这里从第零列开始记录 { cin>>maps[i][j]; } int tot = 0;//tot用来记录有多少种可能性 for(int i =0;i<(1<<n);i++)//遍历每一种情况 { if(i & (i << 1)) continue; //出现相邻直接过掉 mp[tot++] =i; } int ans = 0;//用来记录结果 for(int i = 0; i < n; i++){//遍历每一行因为从0开始,所以下面为i+1 for(int j = 0; j < tot; j++){ //遍历当前行的每一种状态 int sum = 0; //用来记录当前状态第i+1行的总和 REP(l,n){ int t = 1<<l; if(mp[j]&t) sum += maps[i+1][l]; } for(int k = 0; k < tot; k++){ //遍历上一行状态 if(mp[j] & mp[k]) continue; //两行之间有相邻 dp[i+1][j] = max(dp[i+1][j],sum+dp[i][k]);//截止到i+1行为j状态是的最大值 ans = max(ans,dp[i+1][j]);//答案应取每一个最大状态的最大值 } } } cout<<ans<<endl; } return 0; }
相关文章推荐
- hdu1551Cable master(二分*)
- c++引入额外开销的情况
- Oracle之DataGurd(DG)环境搭建
- c++ 流基本概念
- mini-xml(mxml)开发手册--目录
- HDU 1372 Knight Moves ( BFS & DBFS )
- Android进程内通信
- hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //灵活运用最大流量
- KVM虚拟机IO处理过程(二) ----QEMU/KVM I/O 处理过程
- WMS8_仓库配置
- 设计模式
- Hibernate各种主键生成策略与配置详解
- LDD:Ch 2 构造和运行模块
- html5/css3响应式布局
- Java基础-----集合
- hdoj 2199 Can you solve this equation?【二分法】
- poj-1789 Truck History
- poj-1789--Truck History-最小生成数
- hdu5328_Problem Killer(简单dp)
- Odoo HR Payslip