hdu 1565 方格取数(1) 状态压缩dp
方格取数(1)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3848 Accepted Submission(s): 1473
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- using namespace std;
- int a[][];
- int dp1[<<],before[<<],now[<<];
- void prepare(int i,int n)//预处理
- {
- int j,k,s;
- k=<<n;
- for(j=; j<k; j++)
- {
- dp1[j]=;
- for(s=; s<=n; s++)
- {
- if( (j&(<<(s-))) == (<<(s-)) )//包含了这个数字
- dp1[j]=dp1[j]+a[i][s];
- }
- }
- }
- bool panduan(int b,int n)
- {
- int i,x;
- x=;
- for(i=; i<n; i++)
- {
- if( (x&b) == x) return false;
- x=x<<;
- }
- return true;
- }
- int main()
- {
- int n;
- int i,j,s,k,hxl;
- scanf("%d",&n);
- {
- for(i=; i<=n; i++)
- for(j=; j<=n; j++)
- scanf("%d",&a[i][j]);
- memset(now,,sizeof(now));
- memset(before,,sizeof(before));
- k=<<n;
- for(i=; i<=n; i++)
- {
- prepare(i,n);
- for(j=; j<k; j++)
- if(panduan(j,n))
- {
- hxl=;
- for(s=; s<k; s++)
- {
- if( (s&j)> ) continue;
- if(before[s]>hxl)
- hxl=before[s];
- }
- dp1[j]=dp1[j]+hxl;
- }
- for(j=; j<k; j++)
- {
- now[j]=dp1[j];
- before[j]=now[j];
- }
- }
- hxl=;
- for(i=; i<k; i++)
- if(now[i]>hxl) hxl=now[i];
- printf("%d\n",hxl);
- }
- return ;
- }
优化:
很多地方可以优化。
1.其实,可以预处理相邻的情况。不要每一次都判断。就像打表一样。//怎么处理的呢?具体看一下代码。
2.预处理相邻的情况后,发现,1<<20的数组,满足条件的只有17711种,这样的话,优化就巨大了。
3.滚动数组。
我的代码,还是不够优化的,960ms
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- int a[][];
- int state[],len;
- int dp[<<],befor[<<];
- void make_init()//预处理,所以的状态
- {
- int i,k;
- k=<<;
- len=;
- for(i=;i<k;i++)
- {
- if( (i&(i<<))> ) continue;
- else state[len++]=i;
- }
- }
- void prepare(int r,int n)//处理每一行的dp值.
- {
- int i,j,k,ans,x;
- k=<<n;
- for(j=;state[j]<k;j++)
- {
- i=state[j];
- dp[i]=;
- x=i;
- ans=;
- while(x)
- {
- if(x&) dp[i]=dp[i]+a[r][ans];
- ans++;
- x=x>>;
- }
- }
- }
- int main()
- {
- int n;
- int i,j,k,s,hxl;
- make_init();
- while(scanf("%d",&n)>)
- {
- for(i=;i<=n;i++)
- for(j=;j<=n;j++)
- scanf("%d",&a[i][j]);
- k=<<n;
- memset(befor,,sizeof(befor));
- for(i=;i<=n;i++) //枚举每一行
- {
- prepare(i,n);
- for(j=;state[j]<k;j++)//枚举每一种 有效 状态
- {
- hxl=;
- for(s=;state[s]<k;s++)//上一行的有效状态
- {
- if( (state[j]&state[s]) >) continue;//没有冲突
- if(befor[state[s]]>hxl)
- hxl=befor[state[s]];
- }
- dp[state[j]]=dp[state[j]]+hxl;
- }
- for(j=;state[j]<k;j++)
- {
- befor[state[j]]=dp[state[j]];
- }
- }
- hxl=;
- for(i=;state[i]<k;i++)
- if(hxl<befor[state[i]]) hxl=befor[state[i]];
- printf("%d\n",hxl);
- }
- return ;
- }
进一步的优化:
看了一下,别人的博客,看到一个很别人开的数组是很小的。why?
我开的dp数组是 dp[1<<22],其实只要开dp[17715];和状态state[17715 ]一样就可以了.
为什么可以呢?
简单说明一下:原来的方法,是和最原始的位置是一一对应,所以,很好理解。
但是,有很多的空间是浪费的。
现在是对应状态一一对应,就是这样。这样数组开的就小很多了。而且速度快一些。
921ms --> 486 ms
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- int a[][];
- int state[],len;
- int dp[],befor[];
- void make_init()//预处理,所以的状态
- {
- int i,k;
- k=<<;
- len=;
- for(i=;i<k;i++)
- {
- if( (i&(i<<))> ) continue;
- else state[len++]=i;
- }
- }
- void prepare(int r,int n)//处理每一行的dp值.
- {
- int j,k,ans,x;
- k=<<n;
- memset(dp,,sizeof(dp));
- for(j=;state[j]<k;j++)
- {
- x=state[j];
- ans=;
- while(x)
- {
- if(x&) dp[j]=dp[j]+a[r][ans];//!!!哈哈。
- ans++;
- x=x>>;
- }
- }
- }
- int main()
- {
- int n;
- int i,j,k,s,hxl;
- make_init();
- while(scanf("%d",&n)>)
- {
- for(i=;i<=n;i++)
- for(j=;j<=n;j++)
- scanf("%d",&a[i][j]);
- k=<<n;
- memset(befor,,sizeof(befor));
- for(i=;i<=n;i++) //枚举每一行
- {
- prepare(i,n);
- for(j=;state[j]<k;j++)//枚举每一种 有效 状态
- {
- hxl=;
- for(s=;state[s]<k;s++)//上一行的有效状态
- {
- if( (state[j]&state[s]) >) continue;//没有冲突
- if(befor[s]>hxl)
- hxl=befor[s];
- }
- dp[j]=dp[j]+hxl;
- }
- for(j=;state[j]<k;j++)
- {
- befor[j]=dp[j];
- }
- }
- hxl=;
- for(i=;state[i]<k;i++)
- if(hxl<befor[i]) hxl=befor[i];
- printf("%d\n",hxl);
- }
- return ;
- }
hdu 1565 方格取数(1) 状态压缩dp的更多相关文章
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...
- HDU1565 方格取数(1)(状态压缩dp)
题目链接. 分析: 说这题是状态压缩dp,其实不是,怎么说呢,题目数据太水了,所以就过了.手动输入n=20的情况,超时.正解是网络流,不太会. A这题时有个细节错了,是dp[i][j]还是dp[i][ ...
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)
HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...
- HDU 1565 方格取数(1) 轮廓线dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...
- hdu 1565 方格取数(1)(状态压缩dp)
方格取数(1) Time Limit: 10000/5000 MS (J ...
- hdu 2167 方格取数 【状压dp】(经典)
<题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的 3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数 ...
- HDU 1565 方格取数(简单状态压缩DP)
http://acm.hdu.edu.cn/showproblem.php?pid=1565 对于每一个数,取或者不取,用0表示不取,1表示取,那么对于每一行的状态,就可以用一个二进制的数来表示.比如 ...
- HDU 1565 方格取数(1)(最大点权独立集)
http://acm.hdu.edu.cn/showproblem.php?pid=1565 题意: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格 ...
- HDU 1565 方格取数 状压dp
题目: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多 ...
随机推荐
- log4j日志+面向切面监控异常
log4j.xml src/main/resources ----------------------------------------------------------------------- ...
- easyui里面的加载tree的两种方式
第一种: 使用EasyUI中Tree 符合EasyUI中Tree的Json格式,我们先看一下,格式是如何的 [{ "id":1, "text":"My ...
- Ionic2使用百度地图API(JS)出现白屏解决方案
最近自学ionic2,写了一个内嵌百度地图JS的demo,实际跑起来之后出现了大家常见的白屏问题.. 最初的实现是这样的: 首先主页内嵌了一个百度地图插件 <div id="Bmap& ...
- iOS中的自由桥接
[摘抄自<iOS 6编程实战>] 与Objective-C库不同,我们在Objective-C中使用标准C语言和Core Foundation类库(CF*方法)不会遵循那些命名约定.这意味 ...
- P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分
$ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的 ...
- elasticsearch-sql插件
elasticsearch DSL语法有些时候比较难懂换成SQL好处理一些,网上找到一个插件 https://github.com/NLPchina/elasticsearch-sql 安装elast ...
- 动手玩转Docker(二)
CentOS7下安装docker: 通过命令uname -r 查看linux内核版本,版本低的话不支持docker. [tim@num root]$ uname -r 3.10.0-514.el7.x ...
- Kafka:Consumer
1.预览 1.1 消费者组(Consumer Group) 一个consumer group可能有若干个consumer实例 同一个group里面,topic的每条信息只能被发送到group下的一个c ...
- [转] Jenkins pipeline 中获取 exit code, stdout and stderr 返回值和输出
[From] https://issues.jenkins-ci.org/browse/JENKINS-44930 其做法是,把stdout定向到一个文件,sh 配置 returnStatus: tr ...
- FreeRTOS-05任务相关API函数
根据正点原子FreeRTOS视频整理 单片机:STM32F207VC FreeRTOS源码版本:v10.0.1 任务相关API函数: 1. main.c /* * */ #include " ...