HDU 2167 Pebbles

题目大意:有个N*N( 3<=N<=15 )方阵, 可从中若干个数, 使其总和最大.取数要求, 当某一个数被选, 其周围8个数都不能选.

题解:记s数组为合法状态,即没有相邻的数字同时被选的二进制数,sum[i][j]表示第i行j状态下数字总和,那么Dp时只要枚举上一行的状态,判断是否可行,就可以转移出这一行每种合法状态的最优解。

#include <cstdio>
#include <cstring>
#include <algotithm>
#define rep(i,n) for(int i=0;i<n;i++)
using namespace std;
int t,i,n,m,k,dp[16][1<<16],a[16][16],sum[16][1<<16],s[1<<16],ans;
int main(){
    char str[112];
    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‘);
        for(i=1;i<n;i++){
            t=0,gets(str);
            for(int j=0;j<len;j+=3)a[i][t++]=(str[j]-‘0‘)*10+(str[j+1]-‘0‘);
        }
        for(i=m=0;i<(1<<n);i++)if((i&(i<<1))==0)s[m++]=i;
        memset(sum,0,sizeof(sum));memset(dp,0,sizeof(dp));
        rep(i,n)rep(j,m)rep(k,n)if(s[j]&(1<<k))sum[i][j]+=a[i][k];
        rep(i,m)dp[0][i]=sum[0][i];
        for(int i=1;i<n;i++)rep(j,m)rep(k,m){
            if(s[j]&s[k])continue;
            if(s[j]&(s[k]>>1))continue;
            if(s[j]&(s[k]<<1))continue;
            dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]);
        }ans=0;
        rep(i,m)ans=max(ans,dp[n-1][i]);
        printf("%d\n",ans);gets(str);
    }return 0;
}
时间: 2024-10-25 13:04:59

HDU 2167 Pebbles的相关文章

HDU 2167 Pebbles(状压DP)

题目链接:Pebbles Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1504    Accepted Submission(s): 865 Problem Description You're given an unlimited number of pebbles to distribute across an N x N gam

HDU 2167 Pebbles (状压DP)

这个题再次犯了没有初始化的毛病,但是样例居然只有第2组不对,其他的都对...而且还没法调试..... 这个题还是很简单的状压.还是把每一行的状态都先预处理出来.然后从第一行往下不断进行状态转移.为了不TLE,应该把每种状态下的和也预处理出来. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #

Pebbles(hdu 2167)

题意:给定一个N*N的方格,让你在里面取出一些数使其和最大,要求每一个数不能与其相邻的8个数同时取出. /* 和hdu1565差不多,只不过在更新的时候考虑斜上方的格子对该格子的影响. */ #include<cstdio> #include<iostream> #include<cstring> #define N 16 using namespace std; int dp[N][1<<N],a[N][N],n,m; char ch[N*4]; void

hdu 2167状态压缩dp

和杭电上的取石子这道题差不多就是多了个斜着也不行    其次就是输入格式了 先预处理下   把所有满足一行的所有状态列出来   并把相应的和求出来 然后按照dp相应的思路求 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int num[20][20]; int mark[1<<16]; int sum[20][1<<16],have[100

HDU 2167 状压DP

方格取数问题,给出n*n矩阵,3<n<15 求能取得的最大和,要求取某个位置的数以后,其周围的8个数字均不能再取 先预处理出来所有的可取状态,n=15时只有1597个状态,然后地推求解即可 #include "stdio.h" #include "string.h" int n,ans; int b[21],a[21][21],s[1700]; int dp[21][70001],sum[21][70001]; int Max(int a,int b)

hdu 2167 方格取数 【状压dp】(经典)

<题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数字周围8个点都不能取,问:取得数字的最大和为多少? 解题分析: 由于对每一个数,有选和不选两种可能,分别对应状态压缩中的1和0,且 n<=15,1<<15不是非常大,因此就可以非常自然的想到状态压缩. 此题要与普通的状压dp不同的是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,

HDU 2167 状压dp方格取数

题意:给出一个数表,规定取出一个数后周围的八个数都不可取,求可获得的最大数字和 思路:状态压缩dp,每一行的取数方法为状态,显然,由于取数规则的限制,可取的状态并不是 1<<size_col,而是非常有限的,我们可以预处理出状态(不超过1600个),大大降低时间复杂度, 运行时间:140ms #include <bits/stdc++.h> using namespace std; int dp[16][1600],sta[1600],len,n; int g[15][15]; v

hdu 2167 题解

题目 题意 一个数字正方形(所有数都是两位的正整数),取了一个数后,它的周围 $ 8 $ 个数都不能被选,问最大取数总和. 注意数据范围 $ 3=< n <=15 $ 我们可能一开始会去想暴力搜索,枚举状态,但很容易发现时间复杂度过高过不去,于是可以去想dp,先预处理出可行状态,然后枚举可行状态,以及行数,进行转移即可. 我们定义 $ f[i][j] $ 表示当前在第 $ i $ 行此时状态为 $ j $ 状态先处理出来这里只要存编号就好了 转移方程 $ f[i][k]=max(f[i][k]

POJ 1185炮兵阵地 (状压DP)

题目链接 POJ 1185 今天艾教留了一大堆线段树,表示做不动了,就补补前面的题.QAQ 这个题,我第一次写还是像前面HDU 2167那样写,发现这次影响第 i 行的还用i-2行那样,那以前的方法就行不通了. 找出所有可行的状态,因为每一行最大只有10列,所以一行里最多有4个,那它可行的状态不多(网上大多数说法最多是60个).用dp[x][i][j]来转移,x表示第x行,i表示第x行的状态,j表示第x-1行的状态.先初始化前两行. 1 #include <cstdio> 2 #include