逼近法(例 poj3208、poj1037)
逼近法是一种很奇妙的算法,以为“逼近”这一种思想在很多的算法中都有体现。诸如:像我们的二分答案,不断地排除决策集合的一半以接近我们的最终答案;我们的树上倍增求 $ LCA $ 算法,一次次的减小我们跳的距离以确定祖先的准确位置;我们的模拟退火需要用一个温度,每次操作后这个温度一定会下降,逼近正确答案;再如我们大多数函数的收敛性,在多次计算后会趋向某一定值;还有我们DP的拼凑与试填的思想也有逼近的味道。
我们逼近的前提就在于我们是否可以在每一次操作后排除一些决策集合,并且是高效的排除。就像:银河系 -> 太阳系 -> 太阳系 -> 地球 -> 中国 -> 湖南 -> 长沙。还有我做出来的第一道逼近题:存在很多长度为 $ n $ 的有26个字母组成的字符串,我们将他们按字典序排序,现在给出序号或字符串,要求输出它对应的序号或字符串。这是一道傻逼题,我们可以试填第一个字母,然后它后面剩余的位置有很多种填法,我们看这么多填法是否大于我们的序号,然后我们从小到大填,这样可以确定第一个字母,紧接着可以推出第二个第三个.....然后就是答案。
虽然写的都是些浅显的东西,但如果这个思想和其他东西串联起来就不见得简单了。好了说白了就是来写题解的,不管这么多了。。。。。。。。。。。。。。。。。。。。
Poj 1037 A decorative fence
大致题意:我们要构建长度为 $ N $ 的排列,使得排列里的每一个元素同时大于或小于旁边两个数。可以预见这样的数很多,我们将这些排列按字典序排序,现在给出序号求对应的排列。
$ solution: $
就是我举的那个例子的一个变形,只不过多了一个限制:(每一个元素同时大于或小于旁边两个数)。这样我们只需要在逼近的时候特判第一个数是大于或小于第二个数(当然不能忘记我们DP第一维始终得是排列长度,这样才符合逼近思想),然后在逼近的同时维护大于和小于即可!
$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int
using namespace std;
ll m;
int t,n,l;
ll f[25][25][2];
bool use[25];
inline ll qr(){
register char ch; register bool sign=0; ll res=0;
while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
return sign?-res:res;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=20; f[1][1][0]=f[1][1][1]=1;
for(rg i=2;i<=n;++i){
for(rg j=1;j<=i;++j){
for(rg k=1;k<j;++k)
f[i][j][1]+=f[i-1][k][0];
for(rg k=j;k<i;++k)
f[i][j][0]+=f[i-1][k][1];
}
} t=qr();
while(t--){
n=qr(); m=qr();
register bool k=0;
for(rg i=1;i<=n;++i) use[i]=0;
for(rg i=1;i<=n;++i){
if(f[n][i][1]>=m){
k=1; l=i; break;
} else m-=f[n][i][1];
if(f[n][i][0]>=m){
k=0; l=i; break;
} else m-=f[n][i][0];
}use[l]=1; printf("%d",l);
for(rg i=n-1;i>=1;--i){
k^=1; rg s=0;
for(rg j=1;j<=n;++j){
if(use[j])continue;; ++s;
if((!k&&j<l)||(k&&j>l)){
if(f[i][s][k]>=m){
l=j; break;
} else m-=f[i][s][k];
}
}printf(" %d",l); use[l]=1;
}puts("");
}
return 0;
}
Poj 3208 Apocalypse Someday
大致题意:我们规定所有含有连续三个数字6的自然数都是“神秘数”。我们将这些数按字典序排序(及时从小到大),现在给出序号,让你求出对应的“神秘数”。
$ solution: $
又是一道变形题,但这一次改的比较难了一点,因为它需要连续的三个六,这给我们的逼近带来了后效性,如果我们确定的上一个数是6,那么这次逼近里面,开头只带有两个数字6的数也会加如决策集合。所以我们DP维护数字长度为i,含有连续的j个六的数字有多少。然后在逼近时另取一个变量来存已经连续确定了几个六然后找准决策集合进行逼近!
$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int
using namespace std;
int t,n,m;
ll f[25][4];
inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
return sign?-res:res;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
f[0][0]=1;
for(rg i=0;i<20;++i){
for(rg j=0;j<3;++j){
f[i+1][j+1]+=f[i][j];
f[i+1][0]+=f[i][j]*9;
}f[i+1][3]+=f[i][3]*10;
} t=qr();
while(t--){
n=qr(); rg k=3;
for(m=3;f[m][3]<n;++m);
for(rg i=m;i>=1;--i){
for(rg j=0;j<=9;++j){
ll tot=f[i-1][3];
if(j==6||!k)
for(rg o=max(k-(j==6),0);o<3;++o)
tot+=f[i-1][o];
if(tot<n)n-=tot;
else{
if(k)j==6?--k:k=3;
printf("%d",j);
break;
}
}
}puts("");
}
return 0;
}
逼近法(例 poj3208、poj1037)的更多相关文章
- Leetcode 11. Container With Most Water(逼近法)
11. Container With Most Water Medium Given n non-negative integers a1, a2, ..., an , where each repr ...
- 最新IP地址数据库 二分逼近&二分查找 高效解析800万大数据之区域分布
最新IP地址数据库 来自 qqzeng.com 利用二分逼近法(bisection method) ,每秒300多万, 比较高效! 原来的顺序查找算法 效率比较低 readonly string i ...
- POJ 3889 Fractal Streets(逼近模拟)
$ POJ~3889~Fractal~Streets $(模拟) $ solution: $ 这是一道淳朴的模拟题,最近发现这种题目总是可以用逼近法,就再来练练手吧. 首先对于每个编号我们可以用逼近法 ...
- openjudge-膨胀的木棍
http://noi.openjudge.cn/ch0111/09/ 总时间限制: 1000ms 内存限制: 65536kB 描述 当长度为L的一根细木棍的温度升高n度,它会膨胀到新的长度L'=(1 ...
- 分类器的评价指标-ROC&AUC
ROC 曲线:接收者操作特征曲线(receiver operating characteristic curve),是反映敏感性和特异性连续变量的综合指标,roc 曲线上每个点反映着对同一信号刺激的感 ...
- POJ 1905 Expanding Rods 木棍膨胀
描述 当长度为L的一根细木棍的温度升高n度,它会膨胀到新的长度L'=(1+n*C)*L,其中C是热膨胀系数. 当一根细木棍被嵌在两堵墙之间被加热,它将膨胀形成弓形的弧,而这个弓形的弦恰好是未加热前木棍 ...
- P2750 贰五语言Two Five USACO5.5 记忆化搜索
正解:记搜+逼近 解题报告: 神仙题预警,,, 我真滴觉得还是挺难的了,,, 大概说下思路趴QAQ 首先我们要知道逼近法是什么! 逼近法,有点像二分的思路,以这题为例举个eg 假如它给了个数字k.我们 ...
- NOI2001 方程的解数
1735 方程的解数 http://codevs.cn/problem/1735/ 2001年NOI全国竞赛 时间限制: 5 s 空间限制: 64000 KB 题目描述 Descripti ...
- 转载论文关于fir滤波器的fpga实现
摘 要 本文讨论的FIR滤波器因其具有严格的线性相位特性而得到广泛的应用.在工程实践中,往往要求信号处理具有实时性和灵活性,本论文研究FIR的FPGA解决方案正体现了电子系统的微型化和单片化. 本论文 ...
随机推荐
- 【Luogu】P1144最短路计数(BFS)
题目链接 此题使用BFS记录最短路的条数.思路如下:因为是无权无向图,所以只要被BFS到就是最短路径.因此可以记录该点的最短路和最短路的条数:如果点y还没被访问过,则记录dis[y],同时令ans[y ...
- haskell 乱搞笔记[原创]
脑洞时间:为什么世界上有那么多程序语言,那是腐朽的资本主义为了增加广大人民学习成本以及编译原理太过普及造成的,建议大学取消编译原理的一切课程,并挥起奥姆休的剃刀,把所有程序语言统统踢了,除机器 ...
- 济南学习 Day 5 T2 am
車(Rook) [题目描述] 众所周知,車是中国象棋最厉害的棋子之一,他能吃到同一行或者同一列的其他棋子.車显然不能和車在一打起来,于是rly有借来了许多许多車在棋盘上摆了起来...... 他想知道, ...
- Perl语言入门--1--perl的包安装
A. 手工安装 从CPAN下载了DBI模块1.13版的压缩文件DBI-1.13.tar.gz.假设放在/usr/local/src(一般需要编译安装的软件,都放在此目录下安装). # cd /usr ...
- [转发]Android 系统稳定性 - ANR(三)
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之. 编写者:李文栋 http://rayleeya.iteye.com/blog/1956056 1. ...
- python和linux的环境设置/PATH
一.python的环境设置 1.输出path列表: pi@raspberrypi:~$ pythonPython 3.4.0 (default, Jul 1 2014, 09:37:01) [GCC ...
- Wannafly练习赛14
B(倍增) 题意: 分析: 先可以用two point预处理出以每个位置为起点的连续段<=k的下一个终点 然后对于每个询问,倍增跳就行了 时间复杂度O(nlogn) C(扫描线处理区间询问) ...
- CodeWar----求正整数二进制表示中1的个数
Codewars Write a function that takes an integer as input, and returns the number of bits that are eq ...
- amplab
https://github.com/amplab/SparkNet https://amplab.cs.berkeley.edu/
- 老系统优化同步导入10w+Excel数据 秒级
背景:老系统asp.net 2.0项目使用客户反应,某个业务每个月导入数据操作很慢,大致需要15-30分钟才会导入完毕: 分析:导入慢的原因: .数据量过大,且采用的是同步,单个excel shee ...