P1118 [USACO06FEB]Backward Digit Sums G/S

题解:
  (1)暴力法。对1~N这N个数做从小到大的全排列,对每个全排列进行三角形的计算,判断是否等于N。
  对每个排列进行三角形计算,需要O(N2)次。例如第1行有5个数{a,b,c,d,e},那么第2行计算4次,第3行计算3次…等等,总次数是O(N2)的。
  a    b    c    d    e
    a+b    b+c   c+d   d+e
      a+2b+c b+2c+d c+2d+e
       a+3b+3c+d b+3c+3d+e
          a+4b+6c+4d+e
  共有N!=4亿个排列,总复杂度是O ( N ! N 2 ) 的,显然会超时。
  2)三角计算优化+剪枝。
  1)三角计算的优化。对排列进行三角形计算,并不需要按部就班地算,比如{a,b,c,d,e}这5个数,直接算最后一行的公式a+4b+6c+4d+e就好了,复杂度是O(N)的。

不同的N有不同的系数,比如5个数的系数是{1,4,6,4,1},提前算出所有N的系数备用。可以发现,这些系数正好是杨辉三角。
  2)剪枝。即使有了杨辉三角的优化,总复杂度还是有O(N!N),所以必须进行最优性剪枝。对某个排列求三角形和时,如果前面几个元素和已经大于sum,

那么后面的元素就不用再算了。例如,N=9时,计算到排列{2,1,3,4,5,6,7,8,9},如果前5个元素{2,1,3,4,5}求和已经大于sum,那么后面的{6,7,8,9}~{9,8,7,6}都可以跳过,

下一个排序从{2,1,3,4,6,5,7,8,9}开始。本题sum≤12345,和不大,用这个简单的剪枝方法可以通过。
  3)可以用DFS求全排列,也可以直接用STL 的next_permutation()求全排列。

#include <cstdio>
using namespace std; int n,sum;
//以下所有数组的大小都比所需值稍大,是为了防止越界
int visited[25]={0}; //防止重复选数,这是 dfs 枚举排列的要点
int ans[25]; //放置答案
int pc[25];//构造所有i C n-1 int dfs(int i,int num,int v); //写函数原型是(我的)好习惯! int main(void){
scanf("%d%d",&n,&sum);
//下面构造杨辉三角(即组合数表)
pc[0]=pc[n-1]=1; //杨辉三角性质,两边都是1
if (n>1)
for (int i=1;i*2<n;i++)
pc[i]=pc[n-1-i]=(n-i)*pc[i-1]/i; //利用杨辉三角对称性和组合数公式计算
//下面枚举计算
if (dfs(0,0,0)) //0 仅起占位符作用
for (int i=1;i<=n;i++)
printf("%d ",ans[i]); //输出答案
return 0;
} int dfs(int i,int num,int v){
//参数说明:i 表示已经枚举了前 i 个数(数的序号从 1 开始),num 表示第 i 个数是 num,v 表示前 i 个数的“和”为 v
//返回值说明:返回 0 表示不行(不可能),返回 1 表示找到了可行解。利用返回值就可以在找到第一个解后直接返回了
if (v>sum) //“剪枝”,及时排除不可能情况,加速枚举
return 0; //不可能
if (i==n){ //已经枚举了前 n 个(全部),判断一下是否是可行解
if (v==sum){
ans[i]=num; //放置解
return 1;
}
else
return 0;
}
visited[num]=1; //标记一下“第 i 个数的值已经使用过了”
//下面寻找第 i+1 个数
for (int j=1;j<=n;j++){
if (!visited[j] && dfs(i+1,j,v+pc[i]*j)){ //v+pc[i]*j表示前(i+1)个数的“和”
//注意,如果数的序号从 1 开始,那么第 i 个数的系数实际上是 (i-1) C (n-1)
//执行到这里表示已经找到了可行的解
ans[i]=num;
return 1;
}
}
visited[num]=0; //如果没有找到,一定记得复位,为进一步的寻找做准备
return 0; //执行到这里一定是没有找到解
}

P1118 [USACO06FEB]Backward Digit Sums G/S的更多相关文章

  1. BZOJ1653: [Usaco2006 Feb]Backward Digit Sums

    1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 207  Solved:  ...

  2. Backward Digit Sums(POJ 3187)

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5495   Accepted: 31 ...

  3. Backward Digit Sums(暴力)

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5664   Accepted: 32 ...

  4. 1653: [Usaco2006 Feb]Backward Digit Sums

    1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 285  Solved:  ...

  5. POJ3187 Backward Digit Sums 【暴搜】

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4487   Accepted: 25 ...

  6. POJ 3187 Backward Digit Sums 枚举水~

    POJ 3187  Backward Digit Sums http://poj.org/problem?id=3187 题目大意: 给你一个原始的数字序列: 3   1   2   4  他可以相邻 ...

  7. 【POJ - 3187】Backward Digit Sums(搜索)

    -->Backward Digit Sums 直接写中文了 Descriptions: FJ 和 他的奶牛们在玩一个心理游戏.他们以某种方式写下1至N的数字(1<=N<=10). 然 ...

  8. Luogu P1118 [USACO06FEB]数字三角形 Backward Digit Sums | 搜索、数学

    题目链接 思路:设一开始的n个数为a1.a2.a3...an,一步一步合并就可以用a1..an表示出最后剩下来的数,不难发现其中a1..an的系数恰好就是第n层杨辉三角中的数.所以我们可以先处理出第n ...

  9. (DFS、全排列)POJ-3187 Backward Digit Sums

    题目地址 简要题意: 输入两个数n和m,分别表示给你1--n这些整数,将他们按一定顺序摆成一行,按照杨辉三角的计算方式进行求和,求使他们求到最后时结果等于m的排列中字典序最小的一种. 思路分析: 不难 ...

随机推荐

  1. 获取元素在页面中位置 getBoundingClientRect()

    DOM 原生方法getBoundingClientRect()获取元素相对视口位置 DOMRect 对象包含了一组用于描述边框的只读属性--left.top.right和bottom,单位为像素.除了 ...

  2. [C++]-vector 向量

    什么是向量容器 向量容器是一种支持高效的随机访问和高效的尾部插入新元素的容器. 向量容器一般实现为一个动态分配的数组,向量中的元素连续的存放在这个数组中,因此对向量容器进行随机访问具有和动态访问动态数 ...

  3. 如何保证前端项目上线后的安全?webfunny已总结前端最关键的12大指标

    实时监控大屏   众所周知:实时流量大屏,是用来监控前端项目上线质量的. 如大家所知,监控系统会监控线上应用的各项指标,如:错误.白屏.耗时等等,但是仔细一想,即使有这些监控,我们也不一定能够保证线上 ...

  4. Spring Boot 项目集成Redis

    目录 集成方式 使用Jedis 使用spring-data-redis Redis的安装 绑定配置 获取Redis客户端 Redis工具的编写 使用 集成方式 使用Jedis Jedis是Redis官 ...

  5. Spring 学习笔记(3)Spring MVC

    一.什么是 MVC MVC 实际上就是一种设计模式 Model-View-Controller Model 模型其实就是数据,Dao,Bean 等等 View 视图就是所看到的东西,网页,JSP,展示 ...

  6. 一个命令搞定 Web 国际化

    背景 随着出海的业务越来越多,web 应用面临越来越多的国际化的工作.如何高效,高质量的完成 Web 前端国际化工作,已经是摆在 web 前端同学的急需解决的问题. i18n-helper-cli 是 ...

  7. 启动Django报错:SyntaxError: Generator expression must be parenthesized 解决办法

    这是因为版本不兼容所导致的. 此错误已知与Python问题#32012相关.基于Django 1.11.16及以下的项目将在Python 3.7启动时引发此异常.此问题的补丁已合并到Django 2. ...

  8. netty系列之:在netty中使用protobuf协议

    目录 简介 定义protobuf 定义handler 设置ChannelPipeline 构建client和server端并运行 总结 简介 netty中有很多适配不同协议的编码工具,对于流行的goo ...

  9. 熟悉而陌生的新朋友——IAsyncDisposable

    本文作者--句幽 在.NET Core 3.0的版本更新中,官方我们带来了一个新的接口 IAsyncDisposable. 小伙伴一看肯定就知道,它和.NET中原有的IDisposable接口肯定有着 ...

  10. js函数聚合

    //掺杂类实现聚合(有的时候,我们需要某个或多个类里的一些方法函数) //将要被聚合的函数 var JSON = { toJsonString: function () { var output = ...