这个题目的意思是给定k,n( k,n<=7)
并给定k行每行有几个连续的空格,所有的行左对齐,每一行最多7个,下面的行的空格数<=上面相邻行的空格数
给定一个填数字的规则,当对于任意位置i,j , num[ i ][ j ] > num[ i-1 ][ j ] && num[ i ][ j ] >= num[ i ][ j-1 ] 问有(只用数字1->n)有多少种填满空格的方案。
解:
对于直接定义前每一行被填成了什么数,当前走到了第几行,这样的状态状态总数为7*7^7,状态转移为sum(7 - numi),空间时间都受不了。
那么,对于本题目还有一个性质,对于任意的一列其数值成增长趋势,那么所有列的状态最多不超过 2^7(可以想一想为什么)
那么定义d[ i ][ s ]代表走到第i列,前一列的状态是s( s为二进制数最大为(1<<7)-1 , 对于任意位置该位置为1 代表选了i, 0代表没选,1的个数即和该列空格数相同)
那么状态转移就很明显了,不多说了,可以按1的个数,将2^n个状态分到不同数组里,来优化状态转移。
每个状态的最大转移为 c(7,3) = 7*6*5/3/2= 35;
最大代价一定比 (7 * 2^7 * 35 = 31360) 小
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <set> #include <map> #include <string> #include <list> #include <cstdlib> #include <queue> #include <stack> #include <cmath> #define ALL(a) a.begin(), a.end() #define clr(a, x) memset(a, x, sizeof a) #define fst first #define snd second #define pb push_back #define ls (rt<<1) #define rs (ls|1) #define lson l, mid, ls #define rson mid+1, r, rs #define rep(i,n) for(int i=0;i<(int)n;i++) #define rep1(i,x,y) for(int i=x;i<=(int)y;i++) #define sqr(x) ((x)*(x)) using namespace std; typedef long long LL; typedef long long ll; typedef pair<int, int> pii; const int N = 10; const int M = 1<<7; int bitcount(int x) { return (x==0 ? 0:bitcount(x/2)+(x&1)); } vector<int> G[N]; int a[N],l[N],k,n; void init() { for(int i=1; i<N; i++) G[i].clear(); int lim = (1<<n); for(int i=1; i<lim; i++) { G[bitcount(i)].push_back(i); } G[0].clear(); G[0].push_back(0); for(int i=1; i<=a[1]; i++) { l[i] = 0; for(int j=1; j<=k && a[j]>=i; j++) l[i]++; } } int c1[N],c2[N],t1,t2; inline int judge(int s,int ps) { t1 = 0, t2 = 0; for(int i=0; i<n; i++) if(s&(1<<i)) c1[++t1]=i; for(int i=0; i<n; i++) if(ps&(1<<i)) c2[++t2]=i; for(int i=1; i<=t2; i++) if(c2[i]<c1[i]) return 0; return 1; } ll d[N][M]; int main() { while(scanf("%d",&k)==1) { for(int i=1; i<=k; i++) { scanf("%d",&a[i]); } scanf("%d",&n); init(); int tn=a[1]; l[0]=0; for(int i=tn+1; i>=1; i--) { int p = l[i-1]; for(int j=0; j<G[p].size(); j++) { if(i == tn+1) { d[i][G[p][j]] = 1; continue; } d[i][G[p][j]] = 0; if(i==1) { for(int q = 0; q<G[l[i]].size(); q++) d[i][G[p][j]]=d[i][G[p][j]]+d[i+1][G[l[i]][q]]; } else { for(int q = 0; q<G[l[i]].size(); q++) if(judge(G[p][j],G[l[i]][q])) { d[i][G[p][j]]=d[i][G[p][j]]+d[i+1][G[l[i]][q]]; } } } } printf("%lld\n",d[1][0]); } return 0; }
,