codeforces Diagrams & Tableaux1 (状压DP)

http://codeforces.com/gym/100405

D题

题在pdf里

codeforces.com/gym/100405/attachments/download/2331/20132014-acmicpc-northwestern-european-regional-contest-nwerc-13-en.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。

代码:

 //#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll long long
#define usll unsigned ll
#define mz(array) memset(array, 0, sizeof(array))
#define mf1(array) memset(array, -1, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(i=0;i<(n);i++)
#define FOR(i,x,n) for(i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) printf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("huzhi.txt","w",stdout)
#define mp make_pair
#define pb push_back
#define pf push_front
#define ppf pop_front
#define ppb pop_back
const double pi=acos(-1.0);
const double eps=1e-; int k,n;
int a[]; //int cntt[133];
int cnt(int st) {
//if(cntt[st]!=-1)return cntt[st];
int t=,tt=st;
while(tt) {
if(tt&)t++;
tt>>=;
}
//cntt[st]=t;
return t;
} //int okk[133][133];
int ok(int j,int k) {
//if(okk[j][k]!=-1)return okk[j][k];
if(cnt(j)<cnt(k)) {
//okk[j][k]=0;
return ;
}
int tk=k,tj=j,ck=,cj=;
while(tk) {
if(tk&==) {
while(tj) {
if(tj&==) {
if(cj>ck) {
//okk[j][k]=0;
return ;
}
cj++;
tj>>=;
break;
}
cj++;
tj>>=;
if(!tj)while();
}
}
ck++;
tk>>=;
}
//okk[j][k]=1;
return ;
} ll d[][];
int c[],mj; ll farm() {
int i,j;
int maxst=<<n;
//printf("maxst = %d\n",maxst);
mz(d);
FOR(k,,maxst-)
if(cnt(k)==c[])d[][k]=; FOR(i,,mj) {
FOR(j,,maxst-) {
FOR(k,,maxst-) {
if(d[i-][j]!= && cnt(k)==c[i] && cnt(j)==c[i-] && ok(j,k)) {
d[i][k]+=d[i-][j];
//printf("d[%d][%x]=%I64d , d[%d][%x]=%I64d\n",i-1,j,d[i-1][j] ,i,k,d[i][k]);
}
}
}
}
ll re=;
FOR(i,,maxst-)re+=d[mj][i];
return re;
} int main() {
int i,j;
//mf1(cntt);
//mf1(okk);
while(RD(k)!=EOF) {
mz(c);
FOR(i,,k) {
RD(a[i]);
FOR(j,,a[i])c[j]++;
}
mj=a[];
RD(n);
printf("%I64d\n",farm());
}
return ;
}
上一篇:GUI


下一篇:leetcode 438. 找到字符串中所有字母异位词