zoukankan      html  css  js  c++  java
  • DP大作战—状态压缩dp

    题目描述

    阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了。现在,零崎要在地图上布置一片阿姆斯特朗回旋加速式阿姆斯特朗炮,那么在N行M列单位长度大小的地图上,求解阿姆斯特朗回旋加速式阿姆斯特朗炮最大的部署数量和对应部署方案总数。

    输入

    每组输入一行,为两个整数N,M (N <= 100;M <= 10)

    输出

    每组一行两个整数,

    第一个为阿姆斯特朗回旋加速式阿姆斯特朗炮的个数,第二个为此数量下的摆放方式总数。

    输入样例

    3 3

    输出样例

    3 6

    Hint

    100   1为阿姆斯特朗回旋加速式阿姆斯特朗炮的位置,方案不唯一。  
    010
    001

    状态压缩是一种特殊的技巧,不止可以用在dp中。状态压缩其实是在利用数据结构,由于基础数据类型int有32位,一个int变量就可以表示2^32个状态。状态压缩其实是一种优化方法,有很大局限性。第一,单元状态通常只有两种(0、1,其实多了压缩的道理是一样的,但是没有位运算就没什么优势了),第二,单元维度通常不超过50 ( int才32,多了longlong都爆掉难道用高精度大整数压缩不成……)

    状压dp本质上还是dp,问题大多数还是求解最大值或者解决方案总数之类的,但是状态数量巨大普通方法难以表示,所以利用整数可以将状态维度压缩到1维。

    题目来源:http://biancheng.love/contest/10/problem/G/index

    解题思路:

    状态压缩dp问题。

    关于状态压缩问题参见:http://www.cnblogs.com/avril/p/3282295.html

    其他状态压缩DP问题:【POJ3254】【POJ1185】【POJ3311】【HDU3001】【POJ2288】【ZOJ4257】【POJ2411】【HDU3681】

    给出本题代码:

     1 #include <bits/stdc++.h>
     2 #define INF 99999999
     3 typedef long long LL;
     4 using namespace std;
     5 
     6 const int MAX=100+10;
     7 int n,m,lastsize,lastlastsize,nowsize;
     8 int last[MAX],lastlast[MAX],now[MAX];
     9 int num[MAX],dp[MAX][MAX],temp[MAX][MAX];//dp[k][i][j]表示第k行选择i方案,第k-1行选择j方案的最大炮兵数
    10 
    11 void dfs(int id,int k,int p,int sum)
    12 {
    13     if(k>=m)
    14     {
    15         now[++nowsize]=p;
    16         num[nowsize]=sum;
    17         return;
    18     }
    19     dfs(id,k+3,p|(1<<k),sum+1);
    20     dfs(id,k+1,p,sum);
    21 }
    22 
    23 void DP()
    24 {
    25     for(int k=1; k<=n; ++k)
    26     {
    27         memset(now,0,sizeof now);
    28         nowsize=0;
    29         dfs(k,0,0,0);
    30         for(int i=1; i<=nowsize; ++i)for(int j=1; j<=lastsize; ++j)dp[i][j]=0;
    31         for(int i=1; i<=nowsize; ++i) //本行选择第几个方案
    32         {
    33             for(int j=1; j<=lastsize; ++j) //上一行选择第几个方案
    34             {
    35                 for(int t=1; t<=lastlastsize; ++t) //上上行选择第几个方案
    36                 {
    37                     if(now[i] & last[j])continue;//与上一行j方案不能共存
    38                     if(now[i] & lastlast[t])continue;//与上上行t方案不能共存
    39                     if(dp[i][j]<temp[j][t]+num[i])dp[i][j]=temp[j][t]+num[i];
    40                 }
    41             }
    42         }
    43         for(int i=1; i<=nowsize; ++i)for(int j=1; j<=lastsize; ++j)temp[i][j]=dp[i][j];
    44         for(int i=1; i<=lastsize; ++i)lastlast[i]=last[i];
    45         lastlastsize=lastsize;
    46         for(int i=1; i<=nowsize; ++i)last[i]=now[i];
    47         lastsize=nowsize;
    48     }
    49 }
    50 
    51 int main()
    52 {
    53     while(~scanf("%d%d",&n,&m))
    54     {
    55         last[1]=lastlast[1]=temp[1][1]=0;
    56         lastsize=lastlastsize=1;
    57         DP();
    58         int sum=0,cot;
    59         for(int i=1; i<=lastsize; ++i)
    60         {
    61             for(int j=1; j<=lastlastsize; ++j)
    62             {
    63                 if(temp[i][j]>sum)
    64                 {
    65                     sum=temp[i][j];
    66                     cot=1;
    67                 }
    68                 else if(temp[i][j]==sum)
    69                     cot++;
    70             }
    71         }
    72         printf("%d %d
    ",sum,cot);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    eclipse乱码解决方法
    撞库攻击:一场需要用户参与的持久战
    网管把握市场需求,其实一点都不可怜 转载于 [http://tonyxiaohome.blog.51cto.com/925273/955589]
    mysql主从不同步,提示更新找不到记录
    安装完MongoDB后尝试mongod -dbpath命令为什么会一直卡在连接端口?
    mysqlslap对mysql进行压力测试
    mysqlslap: Error when connecting to server: 2001 Can't create UNIX socket (24) 解决方法
    MySQL架构
    VMWare linux 打印太多,看不到之前的记录的解决方法总结
    启动Mysql时,提示error 2002 的解决办法
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/4991970.html
Copyright © 2011-2022 走看看