hoj2662状态压缩dp

题意就是说有k个棋子,放在一个棋盘上,不能有相邻的棋子,问一共有多少种方法,啊咧咧,,状态压缩dp嘛,讨论了一上午,下午学弟写了一下代码,,那个惨啊,错的乱七八糟,然后我们三个人就在改啊,,改啊,其实思路还是很清晰的,状态转移方程为 :

dp[i][j][x] += dp[i - 1][j - tmp][y]; 就是说 第i行 用了 j 个棋子 对应x状态下 的方法数 就等于 它 加上 第i-1行 用了j-tmp个棋子,对应y状态 下的方法数。。

当然还需要优化,比如说一开始就要存下那些状态是合法的,用数组保存下来,还有判断x和y 之间能否成为上下行直接使用 & 。ok 代码如下

#include
#include
#include
#include
#include
#include
#include
using namespace std;
long long n,m,k,dp[82][22][1<<9],ans,mm;
long long mark[1<<9],len;
using namespace std;
long long num(long long x)
{
	long long sum=0;
	while(x)
	{
		if(x&1==1)
			sum++;
		x=x>>1;
	}
	return sum;
}
bool judge(long long x)
{

	if(x&(x<<1)) return false;
	return true;
}
int main()
{
	while(scanf("%lld %lld %lld",&n,&m,&k)!=EOF)
	{
	       ans=0;
	       memset(dp,0,sizeof(dp));
	       memset(mark,0,sizeof(mark));
	       len = 0;
	       long long tmpp = n > m ? n : m;
	       m = n > m ? m : n;
	       n = tmpp;
		 for(long long i=0;i<(1<= tmp)
						 	dp[i][j][x] += dp[i - 1][j - tmp][y];
					}
				}
      for(long long i=0;i< len;i++)
            ans += dp[n][k][i];
      printf("%lld\n",ans);
	}
	return 0;
}

开始交各种tle,,发现m要是很大的话会爆,,然后就机智的吧行和列交换一下,妥妥的。 最坑爹的是要用long long 啊,,哎,还是欠考虑啊。

渣渣睡觉去了

你可能感兴趣的:(dp)