[数学][DFS]JZOJ 1764 游戏

Description

  xc抽空光顾了lp的饲养场,在一大堆赞美语之后和lp玩起了一个游戏——
  一个完整的倒三角有n层,第一层有n个数字,为原始数字,接下来每层都比上一层减少1个数字,并有f[i,j]=f[i-1,j]+f[i-1,j+1] ,如
  3  1  2  4
    4  3  6
     7  9
      16
  由xc给出f[n,1],和一个限制max(0<=f[1,i]<=max),lp要迅速回答出字典序最小的f[1]序列,即f[1,1]最小的情况下f[1,2]要最小……以此类推。
  xc觉得这个问题对于lp还是太简单了,于是又添加了一些坏点,以坐标的形式给出,所谓坏点就是f[i,j]恒为0,现在就让大家一起来玩这个游戏吧。

 

Input

  第一行四个数 n,m,max,f[n,1]
  接下来m行,每行一个坐标,表示是一个坏点

Output

  无解则输出-1
  否则输出n行,第i行输出f[1,i],要求f[1]字典序最小
 

Sample Input

3 1 3 4
2 2

Sample Output

1
3
0
 

Data Constraint

 
 

Hint

【数据说明】
  40%的数据:n<=10;m=1;max<=10;f[n,1]<=1,000
  90%的数据:max<=100
  100%的数据:n<=100;m<=20;max<=10,000;0<=f[n,1]<=10,00

分析

我们把它倒过来,然后就会发现它的系数是杨辉三角

然后这个杨辉三角是有阻挡的

在求出最底一层的系数后,我们可以DFS,然后DFS可以有剪枝:当前格所选的数最大不超过 min(max,剩下的数/当前系数)

#include <iostream> 
#include <cstdio>
#include <memory.h>
using namespace std;
const int N=1e2+10;
int n,m,mx,s,a[N],c[N][N];
bool rtn;

void DFS(int dep,int sum) {
    if (sum==s) {
        for (int i=dep;i<=n;i++) a[i]=0;
        rtn=1;
        return;
    }
    if (dep==n+1) return;
    if (c[n][dep]==0) {
        a[dep]=0;DFS(dep+1,sum);
        return;
    }
    for (int i=0;i<=min(mx,(s-sum)/c[n][dep]);i++) {
        a[dep]=i;DFS(dep+1,sum+i*c[n][dep]);
        if (rtn) return;
    }
}

int main() {
    scanf("%d%d%d%d",&n,&m,&mx,&s);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=i;j++) c[i][j]=-1.0;
    c[1][1]=1;
    for (int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),c[n-x+1][y]=0;
    for (int i=2;i<=n;i++)
        for (int j=1;j<=i;j++)
            if (c[i][j]==-1.0) c[i][j]=c[i-1][j-1]+c[i-1][j];
    DFS(1,0);
    if (!rtn) {
        printf("-1");
        return 0;
    }
    for (int i=1;i<=n;i++) printf("%d
",a[i]);
}
View Code
在日渐沉没的世界里,我发现了你。
原文地址:https://www.cnblogs.com/mastervan/p/10902354.html