codeforces Diagrams & Tableaux1 (状压DP)
http://codeforces.com/gym/100405
D题
题在pdf里
D - Diagrams & Tableaux A Young diagram is an arrangement of boxes in rows and columns conforming to the following rules: the boxes in each row and each column are contiguous, the left borders of all rows are aligned, and each row is not longer than the one above. Here are some examples of Young diagrams: A semi-standard Young tableau for a given number N is a Young diagram that has its boxes filled according to the following rules: Each box contains a single integer between 1 and N, inclusive, each integer is greater than or equal to the integer in the box to its left, and each integer is strictly greater than the integer in the box above. Here is a list of all semi-standard Young tableaux for N = 3, based on a particular Young diagram: 1 2 1 1 3 1 1 2 2 1 3 2 1 2 3 1 3 3 2 3 2 2 3 3 Your task is to count how many semi-standard Young tableaux are possible, based on a given Young diagram, with a given N. Input Each test case consists of two lines. The first line of each test case specifies the Young diagram. This line starts with the number k satisfying 1 k 7, the number of rows, followed by k positive integers l1, l2, . . . , lk. These integers specify the number of boxes on each row of the Young diagram, and they satisfy 7 l1 l2 lk 1. The second line contains the integer N, satisfying k N 7. Output For each test case, print one line containing the number of semi-standard Young tableaux based on the given Young diagram, with the given N. 9 Problem D: Diagrams & Tableaux Example input output 1 1 1 1 1 2 2 2 1 4 4 3 2 1 1 4 1 2 20 20 10 |
题意:
给出一个那种形状,由很多个方格组成。每个方格中可以放1~N中的一个数,要求方格中的数大于上面相邻方格中的数,大于等于左边相邻方格的数。求有多少种放法。
给出k,表示有k行,然后给出各行的方格数。然后给出N。
题解:
状压DP。
因为一列要求下面大于上面,即不能等于,每种数字只能用一次,可以用状态的二进制位表示有无哪个数字,于是2^7=128,用0~127就能表示一列的所有状态。
然后状态转移,相邻两列转,枚举所有情况也就127^2。
然后一共最多7列,转转就得了。
注意结果大,用long long。
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define mf1(array) memset(array, -1, sizeof(array)) 17 #define minf(array) memset(array, 0x3f, sizeof(array)) 18 #define REP(i,n) for(i=0;i<(n);i++) 19 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define WN(x) printf("%d\n",x); 24 #define RE freopen("D.in","r",stdin) 25 #define WE freopen("huzhi.txt","w",stdout) 26 #define mp make_pair 27 #define pb push_back 28 #define pf push_front 29 #define ppf pop_front 30 #define ppb pop_back 31 const double pi=acos(-1.0); 32 const double eps=1e-10; 33 34 int k,n; 35 int a[11]; 36 37 //int cntt[133]; 38 int cnt(int st) { 39 //if(cntt[st]!=-1)return cntt[st]; 40 int t=0,tt=st; 41 while(tt) { 42 if(tt&1)t++; 43 tt>>=1; 44 } 45 //cntt[st]=t; 46 return t; 47 } 48 49 //int okk[133][133]; 50 int ok(int j,int k) { 51 //if(okk[j][k]!=-1)return okk[j][k]; 52 if(cnt(j)<cnt(k)) { 53 //okk[j][k]=0; 54 return 0; 55 } 56 int tk=k,tj=j,ck=0,cj=0; 57 while(tk) { 58 if(tk&1==1) { 59 while(tj) { 60 if(tj&1==1) { 61 if(cj>ck) { 62 //okk[j][k]=0; 63 return 0; 64 } 65 cj++; 66 tj>>=1; 67 break; 68 } 69 cj++; 70 tj>>=1; 71 if(!tj)while(1); 72 } 73 } 74 ck++; 75 tk>>=1; 76 } 77 //okk[j][k]=1; 78 return 1; 79 } 80 81 ll d[11][133]; 82 int c[11],mj; 83 84 ll farm() { 85 int i,j; 86 int maxst=1<<n; 87 //printf("maxst = %d\n",maxst); 88 mz(d); 89 FOR(k,0,maxst-1) 90 if(cnt(k)==c[1])d[1][k]=1; 91 92 FOR(i,2,mj) { 93 FOR(j,0,maxst-1) { 94 FOR(k,0,maxst-1) { 95 if(d[i-1][j]!=0 && cnt(k)==c[i] && cnt(j)==c[i-1] && ok(j,k)) { 96 d[i][k]+=d[i-1][j]; 97 //printf("d[%d][%x]=%I64d , d[%d][%x]=%I64d\n",i-1,j,d[i-1][j] ,i,k,d[i][k]); 98 } 99 } 100 } 101 } 102 ll re=0; 103 FOR(i,0,maxst-1)re+=d[mj][i]; 104 return re; 105 } 106 107 int main() { 108 int i,j; 109 //mf1(cntt); 110 //mf1(okk); 111 while(RD(k)!=EOF) { 112 mz(c); 113 FOR(i,1,k) { 114 RD(a[i]); 115 FOR(j,1,a[i])c[j]++; 116 } 117 mj=a[1]; 118 RD(n); 119 printf("%I64d\n",farm()); 120 } 121 return 0; 122 }