您的位置:首页 > 产品设计 > UI/UE

2014 UESTC Training for Dynamic Programming J

2014-06-02 12:05 393 查看
为了区分横放竖放,横的矩形就两个都是1,纵的矩形就是上一个是0,下一个是1(同列)

这样的话最后一行必然全是1.于是可以从最后一行开始推,

最开始是当前行和上一行是的并是(1<<M)-1,两数交是预处理出的合法状态,500+MS

就然后其实从当前行推到下一行是固定的,已知一行的状态可达到的下一行的状态是很少的

所以这里可以优化

用一个vector,convert[],convert[i][j]=y;表示状态值i可推出的第j个状态的值为K

于是可以DFS出这里所有的vector,方法是不断的置位,其中注意不能再同一列中有两个连续的0;

|3 表示直接移2位。横向1*2矩形 (11)。这项就生成了vector数组

于是初始化就是dp
[(1<<M)-1]=1;其余全部为0

转移dp[i-1][convert[j][k]]+=dp[i][j];

答案就是dp[0][(1<<M)-1]

时间是9ms

#include <map>
#include <set>
#include <list>
#include <cmath>
#include<cctype>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b)
{
return a % b == 0 ? b : gcd(b, a % b);
}
vector <int >convert[2050];//当前行可以达到的下一行
LL dp[14][2050];
int N,M;
void init()
{
if (N<M) swap(N,M);
memset(dp,0,sizeof(dp));
dp
[(1<<M)-1]=1;
for (int i=0;i<(1<<M);i++)
convert[i].clear();
}
void dfs(int cur ,int x,int y)
{
if (cur>=M)
{
if (x<(1<<M) && y<(1<<M))
convert[x].push_back(y);
return ;
}
dfs(cur+1,x<<1,(y<<1)|1);
dfs(cur+1,(x<<1)|1,y<<1);
dfs(cur+2,(x<<2)|3,(y<<2)|3);
}
void slove()
{
dfs(0,0,0);
for (int i=N;i>=1;i--)
for (int j=0;j<(1<<M);j++)
for (int k=0;k<convert[j].size();k++)
dp[i-1][convert[j][k]]+=dp[i][j];
printf("%lld\n",dp[0][(1<<M)-1]);
}
int main()
{
while (scanf("%d%d",&N,&M)!=EOF)
{
if (N==0 && M==0 ) break;
init();
slove();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: