hdu2167 http://acm.hdu.edu.cn/showproblem.php?pid=2167

给定一个N*N的板子,里面有N*N个数字,选中一些数字,使得和最大

要求任意两个选中的数字不相邻,相邻包括上下,左右和对角线相邻。

由于N<=15,用程序判断了一下,每一行的有效状态<1600个,如果记录这些状态,然后每一行枚举当前行的上一行的状态那么极端下有1600*1600*15的复杂度,TLE

所以卡在这里很久,想不到怎么优化。 然后看了别人的代码知道了用邻接表存储哪两个状态是相容的。这样就不用枚举那么多了。所以就过了。

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
using namespace std;
int matrix[][];
int dp[<<][],situation[],bit[],head[],e;
struct node
{
int v,next;
}g[];;
int max(const int &a, const int &b)
{
return a < b ? b : a;
} void addEdge(int u, int v)
{
g[e].v = v;
g[e].next = head[u];
head[u] = e++;
}
int count(int i, int ss, int n)//计算状体第i行的状态s所取的数的和
{
int ret = ;
int j = ;
for(j=; j<n; ++j)
{
if(bit[j] & ss)
ret += matrix[i][j];
}
return ret;
}
bool check(int s, int ss,int n)//检查s和ss是否可容
{ if(s&ss) return false;
if((s<<)&ss) return false;
if((s>>)&ss) return false;
return true;
}
int main()
{
int n,i,j,m,s,ss;
char str[];
bit[i=] = ;
for(i=; i<; ++i)
bit[i] = bit[i-]<<;
m = <<;
for(i=,j=; i<m; ++i)
if(!(i&(i<<)))//求出有效的状态
situation[j++]= i;
while(gets(str))
{
memset(dp,,sizeof(dp));
e = ;
memset(head,-,sizeof(head));
n = ;
do
{
j = ;
stringstream scin(str);
while(scin>>matrix[n][j]) j++;
n++;
gets(str);
if(str[]=='\0') break; }while(true);
m = <<n;
for(i=;situation[i]<m; ++i)//判断哪两个状体相容,然后用邻接表存储
for(j=; situation[j]<m; ++j)
if(check(situation[i],situation[j],n))
addEdge(i,j);
for(i=; situation[i]<m; ++i)
dp[situation[i]][] = count(,situation[i],n);
for(i=; i<n; ++i)
for(s=;situation[s]<m; ++s)
{
for(j=head[s];j!=-;j=g[j].next)
{
dp[situation[g[j].v]][i] = max(dp[situation[g[j].v]][i],dp[situation[s]][i-]+count(i,situation[g[j].v],n));
}
}
int ans = ;
for(i=; situation[i]<m; ++i)
{
ans = max(ans,dp[situation[i]][n-]);
}
printf("%d\n",ans);
}
return ;
}

poj2411 http://poj.org/problem?id=2411

给定一个N*M的矩形,用1*2的矩阵填充满,问有多少种填充的方法。 N,M<=11

状态压缩dp,时间复杂度是N*(1<<M)*(1<<M),可以使用邻接表存储,哪些状态是相容的,这样子,就不用枚举所有的状态了。

状态是如何转移的呢?

首先第一行的状态必须是:如果有1,那么必须有连续的两个1.即不能有单独的一个1.

这样子是为了,第二行如果竖着放,那么就可以填充第一行的空缺。

怎么判断当前行的状态和上一行的状态不冲突的?详见bool check(int s, int ss)函数注释

 #include <stdio.h>
#include <string.h>
#define LL __int64
int n,m;
int e,head[];
LL dp[<<][];
struct node
{
int v,next;
}g[]; void addEdge(int a, int b)
{
g[e].v = b;
g[e].next = head[a];
head[a] = e++;
}
void swap(int &a, int &b)
{
int t = a;
a = b;
b = t;
}
bool check(int s)
{
while(s)
{
if( (s&) && ((s>>)&))
s>>=;
else if( (s&) && !((s>>)&))
return false;
else if(!(s&))
s>>=; }
return true;
}
bool check(int s, int ss)
{
for(int i=; i<m; ++i)
{
if(!(s&) && !(ss&)) return false;//上一行该位置为0,那么这一行该位置应该竖着放,否则不相容
else if(!(s&)&&(ss&))
{
s>>=;ss>>=;continue;//上一行为0,这一行竖着放
}
else if((s&)&&!(ss&))
{
s>>=;ss>>=;continue;//上一行该位置为1,这一行可以不放
}
else if((s&)&&(ss&))//上一行的该位置和这一行的该位置为1,那么这行的矩形是横着放
{
s>>=,ss>>=;i++;
if((s&)&&(ss&)) //即下一个位置,上一行和这一行都必须为1
{
s>>=;ss>>=;continue;
}
else return false;
}
}
return true;
}
int main()
{
int s,ss,t,i,j;
LL ans;
while(scanf("%d%d",&n,&m),n)
{
memset(dp,,sizeof(dp));
if(n<m) swap(n,m);
ans = ;
t = <<m;
memset(head,-,sizeof(head));
e = ;
for(s=; s<t; ++s)
for(ss=; ss<t; ++ss)
if(check(s,ss))
addEdge(s,ss);
if((n*m)%==)
{
for(s=; s<t; ++s)
if(check(s))
dp[s][] = ;
for(i=; i<n; ++i)
for(s=; s<t; ++s)
for(j=head[s];j!=- && g[j].v<t;j=g[j].next)
dp[g[j].v][i] += dp[s][i-]; ans = dp[(<<m)-][n-];
}
printf("%I64d\n",ans);
}
return ;
}

状态压缩dp(hdu2167,poj2411)的更多相关文章

  1. HDU2167+状态压缩DP

    状态压缩dp 详见代码 /* 状态压缩dp dp[ i ][ j ]:第i行j状态的最大和 dp[i][j] = max( dp[i-1][k]+sum[i][j] ); 题意:给定一个N*N的方格, ...

  2. DP大作战—状态压缩dp

    题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...

  3. HDU1565+状态压缩dp

    简单的压缩状态 dp /* 状态压缩dp 同hdu2167 利用滚动数组!! */ #include<stdio.h> #include<string.h> #include& ...

  4. SGU131 - Hardwood floor(状态压缩DP)

    题目大意 给定一个N*M大小的矩形,要求你用1*2和2*2(缺个角)的砖块把矩形铺满(不能重叠),问总共有多少种铺法? 题解 受POJ2411的影响,怎么都没想到3,4,5,6这几种情况该怎么放置,看 ...

  5. HihoCoder第九周 状态压缩 二 与POJ2411总结

    在此我向各位博友求助,特别想知道除了HihoCoder上面的结果要对1e9+7取余之外,这两道题还有什么其他的问题,都是骨牌覆盖问题,都是状态压缩+dp,为什么我能过poj2411的程序过不了Hiho ...

  6. 状态压缩DP(大佬写的很好,转来看)

    奉上大佬博客 https://blog.csdn.net/accry/article/details/6607703 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的 ...

  7. hoj2662 状态压缩dp

    Pieces Assignment My Tags   (Edit)   Source : zhouguyue   Time limit : 1 sec   Memory limit : 64 M S ...

  8. POJ 3254 Corn Fields(状态压缩DP)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4739   Accepted: 2506 Descr ...

  9. [知识点]状态压缩DP

    // 此博文为迁移而来,写于2015年7月15日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6jf.html 1.前 ...

随机推荐

  1. Spring MVC+JSP实现三级联动

    jsp代码 <script type="text/javascript"> $(function() { initProvinces(); }); /** * 获取省列 ...

  2. Automatic logon configuration on Linux OS

    Automatic logon configuration on Linux OS 1. Regarding to DSA: a) ssh-keygen -t dsa  b) cat ~/.ssh/i ...

  3. html浏览器兼容性的 JavaScript语法

    1.      在FireFox中能够使用与HTML节点对象ID属性值同样的JS变量名称.可是IE中不行. 解决的方法:在命名上区分HTML节点对象ID属性值和JS变量 2.      IE不支持JS ...

  4. [Oracle] 常用工具集之 - SQL*Loader

    SQL*Loader原理 SQL*Loader是Oracle提供的用于数据加载的一种工具,它比较适合业务分析类型数据库(数据仓库),能处理多种格式的平面文件,批量数据装载比传统的数据插入效率更高.其示 ...

  5. Samba &amp; Nginx - Resource temporarily unavailable

    先说说本人的开发环境:Win7 + Editplus + VMware(Centos+Samba+Nginx).用Samba在Centos上把web文件夹(如www)共享,然后在Win7上訪问这个文件 ...

  6. hdu 4274 Spy&#39;s Work(水题)

    Spy's Work Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  7. mysql导出和导入数据库

    出口 在dos计划,切换到mysql按照该文件夹bin下一个.输入以下命令 mysqldump -u root -p nxu_life > nxu_life2.sql 运行完毕后,就能够看到在b ...

  8. 利用Gearman实现并发查询(Multi-Query)

    这个样例是想从数据库查询出几个结果集,一般的做法是,一个接一个的发送查询,然后汇总结果进行输出. 以下我们利用Gearman的gearman_client_run_tasks实现并发的查询,gearm ...

  9. win8 远程桌面 你得凭证不工作

    今天在在登录azure远程桌面时,一直提示你的凭证不工作, 按照网上各种教程都不行, 后来发现在win8中用户名结构中,需要加上本机电脑名比如:“win8\administrator”.

  10. Git详解之六 Git工具(转)

    Git 工具 现在,你已经学习了管理或者维护 Git 仓库,实现代码控制所需的大多数日常命令和工作流程.你已经完成了跟踪和提交文件的基本任务,并且发挥了暂存区和轻量级的特性分支及合并的威力. 接下来你 ...