思路:
建立dp【i】【j】二维数组,表示第i行状态为j的最大取值,不难推出其状态转移方程:dp【i】【j】=max(dp【i】【j】,dp【i-1】【k】+sum),其中sum表示j状态下的取值。
首先我们要了解二进制的表示方法,e.g,当j==5的时候,表示101,也就是在表示取第一个和第三个位子上的数,第二个位子上的数不取。
然后我们可以通过枚举的方法枚举一行里边可以选取的方案,其实就是要把带有相邻的1的情况抛去。那么我们可以使用位运算来解决这个问题;那么具体要如何实现呢?对于与运算(&)计算方式为同位为1结果为1,其余都是0,我们不妨这样来判断一个方案能否有相邻的1存在,例如现在状态为j:
j&(j<<1),假如现在j==7
1 1 1&1 1 1 0=0110,
又假如现在j==5
1 0 1&1 0 1 0 =0;
不难发现如果值不为0,那么就表示这种情况有相邻的1,否则没有。对于这部分的代码实现:
for(int i=0; i
对于这部分的代码实现:
for(int i=0; i=1)
for(int k=0; k
另外注意一个问题,开1<<20的数组会MLE,因为我们直接枚举出cont个可以的方案(没有相邻1)其方案数不会达到这么大,所以我们数组也就不用开辣么大。
AC代码:
#include
#include
#include
using namespace std;
int a[25][25];
int dp[21][200000];
int q[200000];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
for(int i=0; i=1)
for(int k=0; k