• 【NOIP2001】数的划分


    本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1025


    呃,我果然还是不行,连道水题都A不了。

    整理了两种方法,都比较有代表性:搜索和DP。

    搜索显然是穷举k位上每位都是什么数,为了避免重复,要控制使数的大小不下降;另外枚举时要加一个可行性剪枝,if(now+(k-d+1)*i>n) break。

     1 #include<cstdio>
     2 int n,k,ans;
     3 void dfs(int d,int now,int last) {
     4     if(d==k+1) {if(now==n) ++ans;return;}
     5     if(now>=n) return;
     6     for(int i=last;i<=n;++i) {
     7         if(now+(k-d+1)*i>n) break;
     8         dfs(d+1,now+i,i);
     9     }
    10 }
    11 int main() {
    12     scanf("%d%d",&n,&k);
    13     dfs(1,0,1);
    14     printf("%d",ans);
    15     return 0;
    16 }
    AC代码(搜索)

    DP的话,主要是状态转移方程的推导(%dalao)。定义dp[i][j]表示使用j个数表示i的方案数,那么可以分类讨论,如果已选取的数中有1,那么dp[i][j]=dp[i-1][j-1];如果没有1,dp[i][j]=dp[i-j][j],相当于将选好的每个数减1(要求i>j,因为不能有0)。显然dp[i][1]=1,我们再将i从小到大枚举,就可以推出dp[n][k]。

     1 #include<cstdio>
     2 const int maxn=205,maxk=10;
     3 int n,k,dp[maxn][maxk];
     4 int main() {
     5     scanf("%d%d",&n,&k);
     6     for(int i=1;i<=n;++i) dp[i][1]=1;
     7     for(int j=2;j<=k;++j)
     8         for(int i=2;i<=n;++i) {
     9             if(i>j) dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
    10             else dp[i][j]=dp[i-1][j-1];
    11         }
    12     printf("%d",dp[n][k]);
    13     return 0;
    14 }
    AC代码
  • 相关阅读:
    STM32学习笔记1(ADC多通道采样)
    SQL Server索引管理之六大铁律
    如何激励员工?
    第一周学习计划
    山寨STL实现之traits,construct&destruct
    山寨STL实现之内存池
    山寨STL实现之vector
    山寨STL实现之allocator
    Python 开发环境搭建
    Java | Python 流程控制对比
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9737979.html
Copyright © 2020-2023  润新知