hdu_1565_方格取数(1)

来源:互联网 发布:网络人肉违法 编辑:程序博客网 时间:2024/04/30 21:18

各种裸的状态压缩嗯~

中文题就就不翻译了~

http://acm.hdu.edu.cn/showproblem.php?pid=1565

解题思想:

有两个比较重要的地方:

1. 纪录可行状态. 例如当前状态i为101011,那么判定状态是否可行为(i&(i<<1))也就是相邻位去&,若为1则不可行.对于一个20个的数组一共有28658种可行状态,判定后直接打表.

2. dp[2][M]作为滚动数组,我的方法是两个指针交换(很多人都用奇偶数的方法).先初始化第一行,dp[0][i]为第i种状态的总值为多少.接下来对每一行的每一种状态,求其上一行的与其不冲突状态的最大值.

源代码:

#include <myhead.h>const int N=21;const int M=(1<<21);const int NUM=28658;int n,num;int state[NUM];int data[N][N];int dp[2][NUM];void build() {num=0;for(int i=0;i<M;++i) {if(i&(i<<1)) continue;state[num++]=i;}//printf("%d\n",num);}void init() {num=(1<<n);memset(dp,-1,sizeof(dp));for(int i=0;i<n;++i) {for(int j=0;j<n;++j)  {scanf("%d",&data[i][j]);}}}int getDp(int x,int m) {int sum=0;int t=0;while(m) {if(m&1) {sum+=data[x][t];}m>>=1;t++;}return sum;}void work() {int *a=dp[0];int *b=dp[1];for(int i=0;state[i]<num;++i) {a[i]=getDp(0,state[i]);}for(int k=1;k<n;++k) {for(int i=0;state[i]<num;++i) {int max=-1;for(int j=0;state[j]<num;++j) {if(a[j]!=-1 && !(state[j]&state[i])) {checkmax(max,a[j]);}}b[i]=max+getDp(k,state[i]);}swap(a,b);}int ans=-1;for(int i=0;state[i]<num;++i) {checkmax(ans,a[i]);}printf("%d\n",ans);}int main() {build();while(~scanf("%d",&n)) {init();work();}return 0;}


原创粉丝点击