标签:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <map> //hoj 2662 状态压缩dp typedef long long LL; LL ans,tag; int m,n,t,d; int i,j,k,l; int st[1<<8], num[1<<8]; /*每个合法状态对应一个cell (map) 存储(k,v) pair: (当行取该状态后的棋子数,方法数) 每个cell存储这个状态的k-v pair*/ std::map<int,LL> MAP[2][1<<8]; void Swap(int &a,int &b) { a = b+a-(b=a); } /*判断数p是否有连续1*/ bool J(int p) { return p&(p<<1); } /*记录一个合法状态p中1的个数*/ int cnt(int p) { l=0; while(p) { if(p&1) { l++; p>>=1; } p>>=1; } return l; } int main() { while(~scanf("%d%d%d",&m,&n,&d)) { t=0; ans=0; if(m<n) { Swap(m,n); } //记录所有合法的状态及个数 for(i=0;i<(1<<n);i++) { if(!J(i)) { num[t]=cnt(i); st[t++]=i; } } for(i=0;i<2;i++) for(j=0;j<t;j++) MAP[i][st[j]].clear(); int up=0,down=1; for(i=0;i<t;i++) { tag=num[i]; if(tag==d) ans++; else if(tag<d) MAP[up][st[i]][tag]=1; } for(i=1;i<m;i++) { for(j=0;j<t;j++) { for(k=0;k<t;k++) { if((st[j]&st[k])==0) { std::map<int,LL>&fa = MAP[up][st[k]]; std::map<int,LL>&son= MAP[down][st[j]]; for(std::map<int,LL>::iterator it=fa.begin();it!=fa.end();it++) { tag=it->first+num[j]; if(tag==d) ans+=it->second; else if(tag<d) son[tag]+=it->second; } } } } /* clear up map, swap up map and down map 因为上一层所有状态的map只对它的下一层有作用 所以每次内存中只保存上下两层map 就可以节省空间 */ for(j=0;j<t;j++) MAP[up][st[j]].clear(); Swap(up,down); } printf("%lld\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zhangzph/p/4480518.html