zoukankan      html  css  js  c++  java
  • 状压dp(B

    题目链接:https://cn.vjudge.net/contest/276236#problem/B

    题目大意:略

     具体思路:和我的上一篇写状压dp的思路差不多,不过就是这个题相当于上一个题的升级版,变成了左右,上下都会有限制,并且限制的步数是2,观察数据范围,如果按照上一个题的话,如果要是计算正确的范围取值的话,肯定会超时,所以我们可以先将所有的满足的情况先筛选出来,就算m取到10,总共的情况也就是60种,这样复杂度就大大的降下来了。

    我们可以先预处理第一行和第二行,这样的话,我们就可以直接从第三行进行操作了,如果只是预处理第一行的话,第二行在往上走的时候,会取到第0行,而这一行我们是没有赋值的,所以我们应该预处理第一行和第二行。从第3行就可以直接进行操作了(就因为这个问题搞了一晚上。。。)。

    我们开一个三维的dp数组,dp[i][j][k]。i代表的是第i行,j代表的是第i行取了哪种情况,k代表的是第i-1行的取值。

    按道理来讲,我们应该一次比较三行的,可是为什么只是处理了两行?

    因为我们在处理第i-1行的时候,我们比较的是dp[i-1][k][t]。这里的t是第i-2行,我们在处理第i行的时候就是按照一次比较三行来的,不过第三行的比较是通过第i-2行来进行比较的。

    AC代码:

     1 #include<iostream>
     2 #include<cmath>
     3 #include<stack>
     4 #include<stdio.h>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std;
     8 # define inf 0x3f3f3f3f
     9 # define ll long long
    10 const int  maxn = 100+10;
    11 char str[maxn];
    12 int a[maxn],ok[maxn],num[maxn];
    13 int dp[maxn][maxn][maxn];
    14 int cal(int t){
    15 int ans=0;
    16 while(t){
    17 ans+=(t&1);
    18 t>>=1;
    19 }
    20 return ans;
    21 }
    22 int main()
    23 {
    24     int n,m;
    25     scanf("%d %d",&n,&m);
    26     for(int i=1; i<=n; i++)
    27     {
    28         scanf("%s",str+1);
    29         for(int j=1; j<=m; j++)
    30         {
    31             if(str[j]=='P')
    32                 a[i]=(a[i]<<1)+1;
    33             else
    34                 a[i]=(a[i]<<1)+0;
    35         }
    36     }
    37     int maxstate=(1<<m)-1;
    38     int ans=0;
    39     for(int i=0; i<=maxstate; i++)
    40     {
    41         if(((i<<1)&i)==0&&(((i>>1)&i)==0)&&(((i>>2)&i)==0)&&(((i>>2)&i)==0))//把合理的情况筛选出来。
    42         {
    43             ok[++ans]=i;
    44             num[ans]=cal(i);//记录一下当前的合理情况的能放的炮弹个数记录下来。
    45         }
    46     }
    47     int maxx=0;
    48     for(int i=1;i<=ans;i++){
    49     if(((ok[i]&a[1])==ok[i]))
    50         dp[1][i][0]=num[i];
    51         maxx=max(maxx,dp[1][i][0]);
    52     }
    53     for(int i=1;i<=ans;i++){
    54     if((ok[i]&a[2])==ok[i]){
    55     for(int j=1;j<=ans;j++){
    56     if(((ok[j]&ok[i])==0)&&((ok[j]&a[1])==ok[j])){
    57     dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+num[i]);
    58     maxx=max(maxx,dp[2][i][j]);
    59     }
    60     }
    61     }
    62     }
    63     for(int i=3;i<=n;i++){
    64     for(int j=1;j<=ans;j++){
    65     if((ok[j]&a[i])==ok[j]){
    66     for(int k=1;k<=ans;k++){
    67     if(((ok[j]&ok[k])==0)&&((ok[k]&a[i-1])==ok[k])){
    68     for(int l=1;l<=ans;l++){
    69     if(((ok[l]&ok[k])==0)&&((ok[l]&ok[j])==0)&&((ok[l]&a[i-2])==ok[l])){//在枚举第i-2行的时候,还需要和第i行和第i-1行进行比较。
    70     dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[j]);
    71     maxx=max(maxx,dp[i][j][k]);
    72     }
    73     }
    74     }
    75     }
    76     }
    77     }
    78     }
    79     printf("%d
    ",maxx);
    80     return 0;
    81 
    82 }
    83  
  • 相关阅读:
    Script:List NLS Parameters and Timezone
    Script:List Buffer Cache Details
    Know about RAC Clusterware Process OPROCD
    RAC Deadlock For Example
    Know more about redo log buffer and latches
    如何设计分区索引
    SCN may jump in a distributed transaction with dblink
    Script to Collect Log File Sync Diagnostic Information (lfsdiag.sql)
    Oracle学习笔记:10046 SQL tracle event
    Oracle学习笔记:创建physical standby
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262747.html
Copyright © 2011-2022 走看看