HDU 2167 Pebbles
2016-04-18 17:06
344 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2167
题意:给一个n×n的格子,每个里面有一个数,如果一个数被选取了,那么它周围的八个位置的数都不可以被选取,问可以选到的最大数之和是多少?
思路:基础状态压缩Dp,按行来递推,dp[i][state]表示第i行的选数状态为state时可以选到的最大值(用二进制数来表状态,比如10010,就是选取当前行的第1个和第4个)。先处理出来一行的可行状态,然后枚举行数,当前行选取数的状态,上一行选取数的状态。答案可以在最后一行的所有可以状态中找到。
题意:给一个n×n的格子,每个里面有一个数,如果一个数被选取了,那么它周围的八个位置的数都不可以被选取,问可以选到的最大数之和是多少?
思路:基础状态压缩Dp,按行来递推,dp[i][state]表示第i行的选数状态为state时可以选到的最大值(用二进制数来表状态,比如10010,就是选取当前行的第1个和第4个)。先处理出来一行的可行状态,然后枚举行数,当前行选取数的状态,上一行选取数的状态。答案可以在最后一行的所有可以状态中找到。
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdlib> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <sstream> #include <queue> #include <utility> using namespace std; #define rep(i,j,k) for (int i=j;i<=k;i++) #define Rrep(i,j,k) for (int i=j;i>=k;i--) #define Clean(x,y) memset(x,y,sizeof(x)) #define LL long long #define ULL unsigned long long #define inf 0x7fffffff #define mod %100000007 int n; int uplim; vector<int> state; char str[1009]; int a[20][20]; int dp[16][1600]; bool check(int x) { if ( x & (x<<1) || x & (x>>1) ) return false; return true; } int cal( int row , int s ) //计算第row行的数,选取状态为s时的得分 { int ans = 0; int k = 0; while( s ) { k++; if ( s & 1 ) { ans+=a[row][k]; } s>>=1; } return ans; } bool init() //读入和预处理 { int x; string temp; getline(cin,temp); stringstream ss(temp); n = 0; while( ss>>x ) { n++; a[1] = x; } if ( !n ) return false; rep(i,2,n) rep(j,1,n) scanf("%d",&a[i][j]); getchar(); getchar(); uplim = 1<<n; Clean(dp,0); state.clear(); rep(i,0,uplim-1) //将所有可行状态筛选出来 if ( check(i) ) state.push_back(i); rep(i,0,state.size()-1) dp[1][i] = cal( 1 , state[i] ); //初始化第一行的值 return true; } bool can(int x,int y) { if ( x & y ) return false; if ( x & (y>>1) ) return false; if ( x & (y<<1) ) return false; return true; } int main() { /* int sum =0; uplim = 1<<15; rep(i,0,uplim-1) if ( check(i) ) sum++; cout<<sum<<endl; //计算最大规模时的可行状态数 */ while( init() ) { rep(i,2,n) //枚举行数 rep(j,0,state.size()-1) // 枚举第i行的状态 { int temp = cal(i,state[j]); //get得分 //printf("%d : %d %d\n",i,state[j],temp); rep(k,0,state.size()-1) //枚举上一行的状态 if ( can(state[j] , state[k]) ) //如果这两个状态可以相邻,就更新答案 dp[i][j] = max( dp[i][j] , dp[i-1][k] + temp ); } int ans = 0; rep(i,0,state.size()-1) ans = max(ans,dp [i]); //找到最大值 cout<<ans<<endl; } return 0; }
相关文章推荐
- Scala进阶源码实战之一——数组、函数基础、流程控制、文件、异常
- Android中程序与Service交互的方式——综述
- JavaScript的变量作用域
- Xcode添加自定义类
- ASP.Net MVC开发基础学习笔记(10):分部视图PartialView
- oracle性能调优-虚拟索引
- 2016年小升初海淀区全部初中排名分析
- tomcat配置虚拟目录的步骤
- 初探博弈论
- 二叉搜索树的后序遍历序列
- 单链表
- linux下安装python工具pip
- php 长整形转字符串
- About QT
- java线程池学习
- 什么是mybatis,mybatis有什么特点
- PowerDesigner 把Comment复制到name中和把name复制到Comment
- 切图教程,PS和AI切图方法分享
- Http规范
- appleDoc 使用