HDU 1565 方格取数(1)

嗯,状态压缩

嗯,其实是一道比较简单的状态压缩,枚举每一种不与上一个状态冲突的情况,然后计算,选择当前状态的最大值

/*状态压缩DP*/
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#define  M 1<<21
#define NUM 28657		//总共的状态数
int num;
int state[NUM];			//存储合法状态
int mat[20][20];		//数据
int dp[2][NUM];	//循环数组实现
int n;
void Init()
{
	int i;
	//得到符合题意的状态数 例如: 1011 & 10110(既1011 <<1 ) =1 可得1011不符合题意  
	//state[]存储每一种合法状态
	for(i=0;i<M;i++){
		if(i&(i<<1))continue;
		state[num++]=i;
	}
}
int get_dp(int i,int x)//状态为x
{
	int t=0,sum =0;
	while(x){
		if(x&1){
			sum += mat[i][t];
		}
		x >>=1;
		t++;
	}
	return sum;
}
void solve()
{
	int i,j,k,x;
	int max ;
	//对第1行进行初始化
	for(i=0;state[i]<num;i++){
		dp[0][i]=get_dp(0,state[i]);
	}
	/*for(i=0;state[i]<num;i++){	//额,查询下是否正确,请无视我等小弱吧!
		printf("<%d>",state[i]);
		printf("<%d>\n",dp[0][i]);
	}*/
	for(i=1;i<n;i++){				//遍历剩余数组
		for(j=0;state[j]<num;j++){	//遍历所有状态
			max = -M;
			for(k=0;state[k]<num;k++){//遍历上一层的所有状态
				if(dp[(i+1)&1][k]!=-1 && (!(state[k]&state[j]))){		//保证上一个状态存在,并且与这次状态不冲突
					x = dp[(i+1)&1][k];
					if(x>max)max = x;									
				}
			}
			dp[i&1][j] = max + get_dp(i,state[j]);
		}
	}
	max = -M;
	i--;
	for(k=0;state[k]<num;k++){				//遍历最后一行, 找最大值
		if(dp[i&1][k] >max)max = dp[i&1][k];
	}
	printf("%d\n",max);
}
int main(){
	int i,j;
	Init();
	while(~scanf("%d",&n)){
		num = 1<<n;
		for(i=0;i<n;i++){
			for(j=0;j<n;j++)
				scanf("%d",&mat[i][j]);
		}
		solve();
		memset(dp,-1,sizeof(dp));
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值