【动态规划13】hdu2167 Pebbles(简单状压dp)

题目描述

You’re given an unlimited number of pebbles to distribute across an N x N game board (N drawn from [3, 15]), where each square on the board contains some positive point value between 10 and 99, inclusive. A 6 x 6 board might look like this:
The player distributes pebbles across the board so that:
?At most one pebble resides in any given square.
?No two pebbles are placed on adjacent squares. Two squares are considered adjacent if they are horizontal, vertical, or even diagonal neighbors. There’s no board wrap, so 44 and 61 of row three aren’t neighbors. Neither are 33 and 75 nor 55 and 92.
The goal is to maximize the number of points claimed by your placement of pebbles.
Write a program that reads in a sequence of boards from an input file and prints to stdout the maximum number of points attainable by an optimal pebble placement for each.

题目大意就是给你一个N <script type="math/tex" id="MathJax-Element-26">*</script>N的棋盘从中取出若干数字,使得总和最大,其中取了一个数字就不能取与它八连通的任意一个数字。

输入输出格式

Each board is expressed as a series of lines, where each line is a space-delimited series of numbers. A blank line marks the end of each board (including the last one)
then your program would print the maximum number of points one can get by optimally distributing pebbles while respecting the two rules, which would be this (each output should be printed on a single line and followed with a newline):

好像没什么可以说的,就是很普通的状压dp,主要是有一个奇怪的优化。
显然对于第i行每一种状态而言,其i+1行对应的可行状态是相同的,那么每次递推的时候不需要再进行判断,可以用邻接表来优化。

http://blog.csdn.net/xingyeyongheng/article/details/21533389
就是从这个大佬的博客里看来的。

#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
const int maxn=30010;
const int mxan=1e5+10;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline int read()
{
    char ls;int x=0,sng=1;
    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    return x*sng;
}
/*----------------------------------------------------------------------------*/
struct kaga
{
    int next;
    int point;
}e[maxn];
int temp[maxn],dp[maxn],ans[maxn];
int a[16][16],c[maxn],cnt;
int last[maxn],k,n;
char str[110];
void init()
{
    memset(dp,0,sizeof(dp));
    memset(temp,0,sizeof(temp));
    memset(last,0,sizeof(last));
    cnt=k=0;
}
void add_edge(int x,int y)
{
    e[++k].next=y;e[k].point=last[x];last[x]=k;
}
void dfs(int k,int p)
{
    if(k>=n){c[++cnt]=p;return;}
    dfs(k+2,p|(1<<k));
    dfs(k+1,p);
}
int calc(int k,int p)
{
    int sum=0;
    fer(i,0,15)
        if(p&(1<<i))sum+=a[k][i];
    return sum;
}
void solve()
{
    dfs(0,0);
    fer(i,1,cnt)
        fer(j,i+1,cnt)
        {
            if(c[i]&c[j])continue;  
            if(c[i]&(c[j]<<1))continue;  
            if(c[i]&(c[j]>>1))continue;
            add_edge(i,j);
            add_edge(j,i);
        }
    fer(k,0,n-1)
    {  
        fer(i,1,cnt)
        {  
            ans[i]=calc(k,c[i]);  
            for(int j=last[i];j;j=e[j].point)
                dp[i]=max(dp[i],temp[e[j].next]+ans[i]);
        }  
        fer(i,1,cnt)temp[i]=dp[i],dp[i]=0;  
    }  
}
int main()
{
    while(gets(str))  
    {  
        int len=strlen(str);  
        n=0;  
        for(int i=0;i<len;i+=3)  
            a[0][n++]=(str[i]-'0')*10+(str[i+1]-'0');
        fer(i,1,n-1)
        {  
            int m=0;  
            gets(str);  
            for(int j=0;j<len;j+=3)  
                a[i][m++]=(str[j]-'0')*10+(str[j+1]-'0');  
        }
        init();
        solve();
        int sum=0;  
        for(int i=1;i<=cnt;++i)sum=max(sum,temp[i]);  
        printf("%d\n",sum);  
        getchar();
    }  
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值