• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
FM_自由人
博客园    首页    新随笔    联系   管理    订阅  订阅

炮兵阵地 poj 1185

ac的第一题状态压缩的dp。状态涉及前两行,通过“加一维”的方式能够解决。还要注意由于炮兵的限制,能够符合的所有排列其实非常少(远小于2^10,据说在70个左右)知道这一点,预处理出所有可能的状态,再通过其他限制条件(地形,前两行状态)进行筛选。
F[i,j,k]表示第i行,i-1行的状态为j,i-2行状态为k。不包括第i行最多能布置多少炮兵。F[i+1,v,j] = MAX( F[i+1,v,j],F[i,j,k] + sum[v] )。sum[v]表示v排列(行排列)有多少个炮兵。状态转移的要求是v,j,k兼容,并且v与第i行地形兼容。
所以枚举 i,j,k,v 效率 O( n*PSB^3 ) PSB表示所有可能的行排列

#include <iostream>
#include
<assert.h>
#include
<stdlib.h>
using namespace std;

#define MAX(a,b) ((a)>(b)?(a):(b))
//垂直方向上的兼容判断 也可判断状态是否适应地形
#define FIT(a,b) (!((a)&(b)))

const int _D_MAXN = 110;
const int _D_MAXM = 11;
const int _D_POSSIBLE = 100;
const int _D_MINEST = -1000000;

int _gn,_gm,_gpbCnt,_gmap[_D_MAXN];
int _gposb[_D_POSSIBLE],_gsum[_D_POSSIBLE],_gdp[_D_MAXN][_D_POSSIBLE][_D_POSSIBLE];

int _fcnt( int s )
{
int cnt = 0;
for( int i = 0;i < _gm;++i )
if( s & (1<<i) ) ++cnt;
return cnt;
}

void _fgetPossible() //init _gposb
{
_gpbCnt
= 0;
//注意_gposb[0] = 0;
for( int i = 0,tot = 1 << _gm;i < tot;++i )
{
if( (i&(i<<1) || (i&(i<<2))) ) continue; //水平 相邻1距离在2以上
if( (i&(i>>1) || (i&(i>>2))) ) continue;
_gposb[_gpbCnt]
= i;
_gsum[_gpbCnt
++] = _fcnt(i);
}
}

void _finit()
{
cin
>> _gn >> _gm;
_fgetPossible();
char c;
for( int i = 0;i < _gn;++i )
{
_gmap[i]
= 0;
for( int j = 0;j < _gm;++j )
{
cin
>> c;
if( c == 'H' ) _gmap[i] |= (1<<j); //山地
}
for( int p1 = 0;p1 < _gpbCnt;++p1 )
for( int p2 = 0;p2 < _gpbCnt;++p2 )
_gdp[i][p1][p2]
= _D_MINEST;
}
}

int main()
{
//system("pause");
_finit();
// //第二行 初始化
// for( int sc = 0;sc < _gpbCnt;++sc )
// {
// int ns = _gposb[sc];
// if( FIT(ns,_gmap[0]) ) _gdp[1][sc][0] = MAX(_gdp[1][sc][0],_gsum[sc]);
// }

_gdp[
0][0][0] = 0;
for( int i = 0;i < _gn;++i )
{
for( int j = 0;j < _gpbCnt;++j )
for( int k = 0;k < _gpbCnt;++k )
{
if( _gdp[i][j][k] == _D_MINEST ) continue;
for( int sc = 0;sc < _gpbCnt;++sc )
{
int ns = _gposb[sc];
if( FIT(ns,_gposb[j]) && FIT(ns,_gposb[k]) && FIT(ns,_gmap[i]) ) //ok ns符合要求
_gdp[i+1][sc][j] = MAX(_gdp[i+1][sc][j],_gdp[i][j][k] + _gsum[sc] );
}
}
}

int ans = _D_MINEST;
for( int j = 0;j < _gpbCnt;++j )
for( int k = 0;k < _gpbCnt;++k )
ans
= MAX(ans,_gdp[_gn][j][k]); //_gn行不在地图上 但是答案在上面
cout << ans << endl;

// cout << "----------------------" << endl;
// cout << _gpbCnt << endl;
// cout << _gposb[0] << endl;

return 0;
}

posted @ 2011-05-05 22:24  FM_自由人  阅读(126)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3