正题
题目大意
一个n∗nn*nn∗n的矩阵中fi,j=fi−1,j+fi−1,j+1f_{i,j}=f_{i-1,j}+f_{i-1,j+1}fi,j=fi−1,j+fi−1,j+1。
但是有格子恒定为0
给出fn,1f_{n,1}fn,1要求在第一列的数字不超过MaxMaxMax的情况下字典序最小。
求这个字典序。
解题思路
若不考虑坏格子,我们发现
a,b,c,da,b,c,da,b,c,d
a+b,b+c,c+da+b,b+c,c+da+b,b+c,c+d
a+2b+c,b+2c+da+2b+c,b+2c+da+2b+c,b+2c+d
a+3b+3c+da+3b+3c+da+3b+3c+d
也就是fn,1=∑i=1nxif1,if_{n,1}=\sum_{i=1}^nx_if_{1,i}fn,1=i=1∑nxif1,i
那么我们可以计算出每个xxx
fk,i,jf_{k,i,j}fk,i,j表示xkx_kxk在(i,j)(i,j)(i,j)这个位置是多少,那么我们有开始时fk,1,k=1f_{k,1,k}=1fk,1,k=1
且fk,i,j=fk,i−1,j+fk,i−1,j+1f_{k,i,j}=f_{k,i-1,j}+f_{k,i-1,j+1}fk,i,j=fk,i−1,j+fk,i−1,j+1
那么最终对于每个xi=fk,n,1x_i=f_{k,n,1}xi=fk,n,1
然后就可以dfsdfsdfs,加上剪枝就可以过掉。
codecodecode
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110;
int n,m,Big,K,a[N],f[N][N][N];
bool flag,v[N][N];
void dfs(int x,int num)
{int A=f[x][n][1];if(x>n&&num==K){flag=1;for(int i=1;i<=n;i++)printf("%d\n",a[i]);}if(x>n||num>K||flag) return;if(A<=0||A>K){dfs(x+1,num);return;}for(int i=0;i<=Big;i++){if(num+i*A>K) break;a[x]=i;dfs(x+1,num+i*A);}
}
int main()
{scanf("%d%d%d%d",&n,&m,&Big,&K);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);v[x][y]=1;}for(int i=1;i<=n;i++)f[i][1][i]=1;for(int i=2;i<=n;i++)for(int j=1;j<=n-i+1;j++)if(!v[i][j]){for(int k=1;k<=n;k++)f[k][i][j]=f[k][i-1][j]+f[k][i-1][j+1];}dfs(1,0);if(!flag) printf("-1");
}
/*
100 20 10000 8970
9 79
36 25
16 20
41 44
81 4
18 50
13 55
71 3
18 61
81 20
77 8
7 8
67 2
31 39
47 6
6 22
97 1
3 71
39 39
43 3
*/