poj 1185 状态压缩DP

来源:互联网 发布:淘宝清仓报名要求 编辑:程序博客网 时间:2024/04/24 11:54

这题开始直接状态压缩每行 2^M 然后就TLE了。。。。

最后看了下别人的发现其实每行的状态没有这么多,因为相邻两个大炮的距离不能小于2 所以当M为10 的时候每行的状态只有60种,每次在得到M的时候,直接搜出这些状态保存起来,然后就可以了。。。。

AC代码如下:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;int N, M;int st[100], num[100], tot;int dp[2][100][100];char maps[100][10];void getstatu( int statu, int pos, int sum ){    if( pos >= M ){        num[tot] = sum;        st[tot++] = statu;        return;    }    getstatu( statu, pos + 1, sum );    getstatu( statu | ( 1 << pos ), pos + 3, sum + 1 );}bool judge( int r, int now, int pre1, int pre2 ){    for( int i = 0; i < M; i++ ){        if( st[now] & ( 1 << i ) ){            if( maps[r][i] == 'H' || st[pre1] & ( 1 << i ) || st[pre2] & ( 1 << i ) ){                return false;            }        }    }    return true;}int main(){    while( scanf( "%d%d", &N, &M ) != EOF ){        for( int i = 0; i < N; i++ ){            scanf( "%s", maps[i] );        }        tot = 0;        getstatu( 0, 0, 0 );        memset( dp, -1, sizeof( dp ) );        int now = 0;        dp[now][0][0] = 0;        for( int i = 0; i < N; i++ ){            now ^= 1;            memset( dp[now], -1, 100 * 100 * sizeof( int ) );            for( int j = 0; j < tot; j++ ){                for( int k = 0; k < tot; k++ ){                    if( dp[now^1][j][k] != -1 ){                        for( int l = 0; l < tot; l++ ){                            if( judge( i, l, j, k ) ){                                dp[now][l][j] = max( dp[now][l][j], dp[now^1][j][k] + num[l] );                            }                        }                    }                }            }        }        int ans = 0;        for( int i = 0; i < tot; i++ ){            for( int j = 0; j < tot; j++ ){                ans = max( ans, dp[now][i][j] );            }        }        cout << ans << endl;    }    return 0;}


0 0
原创粉丝点击