hdu2167Pebbles

来源:互联网 发布:淘宝网服饰香柳儿 编辑:程序博客网 时间:2024/05/17 07:36

状态压缩的模板题。。。
题意:给你一个N*N( 3<=N<=15)个矩阵,要你选择若干个数(每个数的范围在[10,99]),使得最后所选的数总和最大。选数的规则是如果选了某个数,那么它的八个相邻方向的数都不能选。
刚开始学还是有难度的,这还是我状压第一题。
方法:先状态压缩,将矩阵看作二进制变成一个数,再以第1行为例枚举出所有的情况与最优解,存在v,f数组,再更新下面2~n行,枚举过程中判断异或一下上、上左、上右有没有选过即可
代码:

#include<cstdio>#include<iostream>#include<cstring>#include<sstream>using namespace std;int f[20][(1<<15)+10];int n,a[20][20],vn,v[(1<<15)+10],bit[20];char s[110000];int main(){    bit[1]=1;for(int i=2;i<=15;i++)bit[i]=bit[i-1]*2;    while(gets(s))    {        stringstream ss(s);        n=0;while(ss>>a[1][++n]);n--;        for(int i=2;i<=n;i++)            for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);        gets(s);gets(s);        memset(f,0,sizeof(f));        int mmax=(1<<n)-1;vn=0;        for(int x=0;x<=mmax;x++)            if(((x<<1)&x)==0)            {                for(int j=1;j<=n;j++)                    if((bit[j]&x)==bit[j])f[1][x]+=a[1][j];                v[++vn]=x;            }        for(int i=2;i<=n;i++)            for(int p=1;p<=vn;p++)            {                int tt=0;for(int j=1;j<=n;j++)                    if((bit[j]&v[p])!=0)tt+=a[i][j];                for(int q=1;q<=vn;q++)                    if((v[q]&v[p])==0&&((v[q]<<1)&v[p])==0&&((v[q]>>1)&v[p])==0)                        f[i][v[p]]=max(f[i][v[p]],f[i-1][v[q]]+tt);            }        int ans=0;for(int p=1;p<=vn;p++)            if(ans<f[n][v[p]])ans=f[n][v[p]];        printf("%d\n",ans);    }    return 0;}

By_yzh

4 1
原创粉丝点击