P1118 [USACO06FEB]数字三角形`Backward Digit Su`… 回溯法
有这么一个游戏:
写出一个11至NN的排列a_iai,然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少11,直到只剩下一个数字位置。下面是一个例子:
3,1,2,43,1,2,4
4,3,64,3,6
7,97,9
1616
最后得到1616这样一个数字。
现在想要倒着玩这样一个游戏,如果知道NN,知道最后得到的数字的大小sumsum,请你求出最初序列a_iai,为11至NN的一个排列。若答案有多种可能,则输出字典序最小的那一个。
[color=red]管理员注:本题描述有误,这里字典序指的是1,2,3,4,5,6,7,8,9,10,11,121,2,3,4,5,6,7,8,9,10,11,12
而不是1,10,11,12,2,3,4,5,6,7,8,91,10,11,12,2,3,4,5,6,7,8,9[/color]
输入输出格式
输入格式:
两个正整数n,sumn,sum。
输出格式:
输出包括11行,为字典序最小的那个答案。
当无解的时候,请什么也不输出。(好奇葩啊)
输入输出样例
说明
对于40\%40%的数据,n≤7n≤7;
对于80\%80%的数据,n≤10n≤10;
对于100\%100%的数据,n≤12,sum≤12345n≤12,sum≤12345。
一开始用模拟法 超时3个点
然后观察发现 累合的乘数为杨辉三角 用杨辉三角优化 超时2个点
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define inf 0x3f3f3f3f
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 105
int a[];
int yhsj[][];
int main()
{
int n;
int sum;
RII(n,sum);
rep(i,,n)
a[i]=i; yhsj[][]=;
rep(i,,n)
rep(j,,i)
yhsj[i][j]=yhsj[i-][j-]+yhsj[i-][j]; int b[];
do
{
int all=;
int ok=;
rep(i,,n)
{
all+=a[i]*yhsj[n][i];
if(all>sum){ok=;break;}
}
if(ok&&all==sum)
{
rep(i,,n)
{
if(i!=)
printf(" ");
printf("%d",a[i]);
}
break;
} }
while(next_permutation(a+,a++n));
return ;
}
2 TLE
参考了大佬的做法
其实只要加一个关键剪枝即可
如果加到i处过不去了 把i及其后面的数降序排列好 下一个next就是 累合杨辉三角的最小值了 !!!!(因为杨辉三角中间大 两边小)
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define inf 0x3f3f3f3f
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 105
int a[];
int yhsj[][];
int main()
{
int n;
int sum;
RII(n,sum);
rep(i,,n)
a[i]=i; yhsj[][]=;
rep(i,,n)
rep(j,,i)
yhsj[i][j]=yhsj[i-][j-]+yhsj[i-][j]; do
{
int all=;
int ok=;
rep(i,,n)
{
all+=a[i]*yhsj[n][i];
if(all>sum){ok=;sort(a+i,a++n,greater<int>()); break;}
}
if(ok&&all==sum)
{
rep(i,,n)
{
if(i!=)
printf(" ");
printf("%d",a[i]);
}
break;
}
}
while(next_permutation(a+,a++n));
return ;
}
其实这题用dfs回溯法更见简单高效 上面那个剪枝其实很难想到
不要过度依赖STL 有时候效率非常低下
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define inf 0x3f3f3f3f
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
//////////////////////////////////
#define N 105 int a[];
int yhsj[][];
int vis[];
int sum,n;
int ok=;
int ans[];
void dfs(int now,int all)
{
if(ok)return ;
if(now==n+&&all==sum)
{
ok=;
rep(i,,n)
{
if(i!=)
printf(" ");
printf("%d",ans[i]);
}
return ;
}
rep(i,,n)
{
if(vis[i])continue;
if(all+i*yhsj[n][now]>sum)continue;
vis[i]=;
ans[now]=i;
dfs(now+,all+i*yhsj[n][now]);
vis[i]=;
}
return ;
}
int main()
{
RII(n,sum);
rep(i,,n)
a[i]=i; yhsj[][]=;
rep(i,,n)
rep(j,,i)
yhsj[i][j]=yhsj[i-][j-]+yhsj[i-][j]; dfs(,); return ;
}
P1118 [USACO06FEB]数字三角形`Backward Digit Su`… 回溯法的更多相关文章
- P1118 [USACO06FEB]数字三角形`Backward Digit Su`…
题目描述 FJ and his cows enjoy playing a mental game. They write down the numbers from 11 to N(1 \le N \ ...
- P1118 [USACO06FEB]数字三角形Backward Digit Su…
题目描述 FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N ...
- 洛谷—— P1118 [USACO06FEB]数字三角形Backward Digit Su…
https://www.luogu.org/problem/show?pid=1118#sub 题目描述 FJ and his cows enjoy playing a mental game. Th ...
- P1118 [USACO06FEB]数字三角形`Backward Digit Su`… (dfs)
https://www.luogu.org/problemnew/show/P1118 看的出来是个dfs 本来打算直接从下到上一顿搜索 但是不会 看了题解才知道系数是个杨辉三角....... 这样就 ...
- 洛谷P1118 [USACO06FEB]数字三角形`Backward Digit Su`…
#include<iostream> using namespace std ; ; int y[N][N]; int n; int a[N]; bool st[N]; int sum; ...
- luoguP1118 [USACO06FEB]数字三角形`Backward Digit Su`… 题解
一上午都在做有关搜索的题目,,, 看到这题之后就直接开始爆搜 结果只有70分, 其余的点硬生生的就是那么WA了. 我的天哪~ 70分代码: #include<iostream> #incl ...
- Luogu P1118 [USACO06FEB]数字三角形 Backward Digit Sums | 搜索、数学
题目链接 思路:设一开始的n个数为a1.a2.a3...an,一步一步合并就可以用a1..an表示出最后剩下来的数,不难发现其中a1..an的系数恰好就是第n层杨辉三角中的数.所以我们可以先处理出第n ...
- 【洛谷P1118】数字三角形
数字三角形 题目链接 4 16 3 1 2 4 3 1 2 4 (3+1) (1+2) (2+4)(3+1+1+2) (1+2+2+4) (3+1+1+1+2+2+2+4)16=1*3+3*1+3*2 ...
- [USACO06FEB]数字三角形
题目描述 FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N ...
随机推荐
- python基础--管理目录与文件
1) 文件夹 os.listdir() #显示文件夹下所有文件 os.getcwd() #获取当前工作目录 os.chdir() #切换目录 os.mkdir() #建立目录 os.path.exis ...
- Codeforces Educational Codeforces Round 57 题解
传送门 Div 2的比赛,前四题还有那么多人过,应该是SB题,就不讲了. 这场比赛一堆计数题,很舒服.(虽然我没打) E. The Top Scorer 其实这题也不难,不知道为什么这么少人过. 考虑 ...
- 初学python之路-day14
一.带参装饰器 # 通常,装饰器为被装饰的函数添加新功能,需要外界的参数 # -- outer参数固定一个,就是func # -- inner参数固定同被装饰的函数,也不能添加新参数 # -- 可以借 ...
- 关于KEIL编译报错和警告问题
编译时候报错.. Library reports error: __use_no_semihosting was requested, but _ttywrch was referenced 上网找了 ...
- vue 树状图数据的循环 递归循环
在main.js中注册一个子组件 在父组件中引用 树状图的数据格式 绑定一个数据传入子组件,子组件props接收数据 子组件中循环调用组件,就实现了递归循环
- ionic3 国际化
http://www.cnblogs.com/huangenai/p/6868173.html 按上面这个网站的步骤整一遍, 但是ionic3 会报错 所以 在 import { NgModule ...
- LeetCode(105):从前序与中序遍历序列构造二叉树
Medium! 题目描述: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inor ...
- 【python】ftp连接,主被动,调试等级
示例代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- import os from ftplib import FTP def ftp_down( ...
- php回调函数的概念及实例
php提供了两个内置函数call_user_func()和call_user_func_array()提供对回调函数的支持.这两个函数的区别是call_user_func_array是以数组的形式接收 ...
- hdu4044 依赖背包变形 好题!
由于不是求最大的可拦截的HP值,而是要将最小值最大化,那么就需要分配每个子树用的钱数以达到最小值最大化 第一步解决如何分配钱使得结点u的子树中用了j元钱后可以拦截的HP最大,这就是变形的分组(依赖)背 ...