HDU 1565 方格取数(简单状态压缩DP)
http://acm.hdu.edu.cn/showproblem.php?pid=1565
对于每一个数,取或者不取,用0表示不取,1表示取,那么对于每一行的状态,就可以用一个二进制的数来表示。比如5的二进制为101,就表示取第一个数,不取第二个数,取第三个数。
将符合要求的状态保存下来,什么是符合要求的呢?即二进制数中不存在相邻的1(110,011都是不符合要求的)。可以用移位并按位与的办法来判断,举个例子:110左移一位为011 ,110&011 = 1,不符合要求;101左移一位为010,101&010=0,符合要求,这是判断同一行时的方法。
判断上下两行,只需将上下两行的状态按位与即可。(PS:在纸上写写,和容易就能看出来)
然后枚举每一行的状态和上一行的状态,找出不与上一个状态冲突的情况,然后计算,选择当前状态的最大值
AC
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int status[];//存状态
int mp[][];
int d[][];//d[i][j]表示第i行第j种状态时的最大和(这时的最大和是1~i行所能取得的最大和)
int n;
///将符合要求的状态保存下来,即没有两个一相邻的情况
int init(int n)
{
int M=;
for(int i= ; i<n ; i++)
if((i&(i>>))==)///不相邻
status[M++] = i;
return M;
}
///计算该状态的和
int cal(int x,int t)
{
int sum=,j=n-;
while(t)
{
if(t&)///最后为是1
sum+=mp[x][j];
j--;
t >>= ;
}
return sum;
}
int main( )
{ while(scanf("%d",&n)!=EOF)
{
if(n == )//加上这句用C++提交能过,没这句C++就过不了,但G++能,不知道为啥
{
printf("0\n");
continue;
}
int M = init(<<n);///初始化,找到状态一有多少
memset(d,,sizeof(d));
for(int i= ; i<n ; i++)
for(int j= ; j<n ; j++)
scanf("%d",&mp[i][j]);
for(int i= ; i<M ; i++)
d[][i]=cal(,status[i]);
for(int i= ; i<n ; i++)///第i行
{
for(int j= ; j<M ; j++)///枚举第i行状态
{
int t=cal(i,status[j]);
for(int k= ; k<M ; k++)///枚举上一行的状态,即第i-1行
{
if(status[j]&status[k])///上一行和这一行存在上下相邻的1
continue;
d[i][j]=max(d[i-][k]+t,d[i][j]);
}
}
}
int ans=;
for(int i=n- , j= ; j<M ; j++)
ans=max(d[i][j],ans);
printf("%d\n",ans); }
return ;
}
HDU 1565 方格取数(简单状态压缩DP)的更多相关文章
- hdu 1565 方格取数(1) 状态压缩dp
方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- 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 方格取数(1)(最大点权独立集)
http://acm.hdu.edu.cn/showproblem.php?pid=1565 题意: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格 ...
- HDU 1565 方格取数 状压dp
题目: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多 ...
随机推荐
- [patl2-001]紧急救援
解题关键:最短路的变形. 1.按顶点存储,$O(n^2)$ #include<cstdio> #include<cstring> #include<algorithm&g ...
- css知多少(6)——选择器的优先级(转)
css知多少(6)——选择器的优先级 1. 引言 上一节<css知多少(5)——选择器>最后提到,选择器类型过多将导致一些问题,是什么问题呢?咱们直接举例子说明. 上图中,css中的两 ...
- POJ 1220 高精度/进制转换
n进制转m进制,虽然知道短除法但是还是不太理解,看了代码理解一些了: 记住这个就好了: for(int k=0;l; ){ for(int i=l ; i>=1 ; i--){ num[i - ...
- Selenium二次封装-Java版本
package com.yanfuchang.selenium.utils; import java.awt.AWTException; import java.awt.Robot; import j ...
- 【转】手把手教你用Strace诊断问题
原博客地址:http://huoding.com/2015/10/16/474 早些年,如果你知道有个 strace 命令,就很牛了,而现在大家基本都知道 strace 了,如果你遇到性能问题求助别人 ...
- Android 之 信息通知栏消息Notification
Notification是安卓手机顶部的消息提示 这里我们分别设置两个按钮,来实现顶部消息的发送和取消 功能实现 首先要在主Activity中设置一个通知控制类 NotificationManager ...
- 数据结构_bubble_sort
问题描述 给定一个 1~N 的排列 P,即 1 到 N 中的每个数在 P 都只出现一次. 现在要对排列 P 进行冒泡排序,代码如下:for (int i = 1; i <= N; ++i)for ...
- 6678 emif norflash加载
终于搞定,纪念一下.CCS6很不好用,还是换回CCS5.5吧!
- 2015年第六届蓝桥杯省赛试题(JavaA组)
1.结果填空 (满分3分)2.结果填空 (满分5分)3.结果填空 (满分9分)4.代码填空 (满分11分)5.代码填空 (满分13分)6.结果填空 (满分17分)7.结果填空 (满分21分)8.程序设 ...
- 多用户ATM机(面向对象编程)
let readline = require('readline-sync'); // 清屏函数 let clear = () => process.stdout.write(process.p ...