逼近法(例 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解决方案正体现了电子系统的微型化和单片化. 本论文 ...
随机推荐
- 开源中国+soucetree
参考链接:http://www.cocoachina.com/programmer/20151012/13682.html 1.创建一个工程
- [BZOJ3339] Rmq Problem(线段树)
传送门 这个题的方法好像很多啊 1.莫队暴力 2.线段树 + 离线处理 先预处理出sg[i]表示前i个数的sg值,next[i]表示i的下一位置在哪里,如果后面再没有i,那么next[i] = n + ...
- VBA Split()函数
Split()函数返回一个数组,其中包含基于分隔符分割的特定数量的值. 语法 Split(expression[,delimiter[,count[,compare]]]) 参数说明 Expressi ...
- BZOJ 1006 [HNOI2008]神奇的国度==最大势算法
神奇的国度 K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在. ...
- 【java小工具】从.java文件中筛选出方法,并计算出方法在这些文件中出现的次数
package getMethod; import java.io.*; import java.util.*; import java.util.regex.Matcher; import java ...
- 【BZOJ2653】middle(主席树,二分)
题意:一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...
- (转)java 中变量存储位置总结
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符 ...
- 【转】3年PHPer的面试总结
[转]3年PHPer的面试总结 算法# 1.反转函数的实现# /** * 反转数组 * @param array $arr * @return array */ function reverse($a ...
- vba功能语句
VBA语句集(第1辑) 定制模块行为(1) Option Explicit '强制对模块内所有变量进行声明Option Private Module '标记模块为私有,仅对同一工程中其它模块有用,在宏 ...
- Java 一个?格式的解决
用Java 出现了这样的一个问题?好几天都没解决掉 然后最近一直找资料 截个图: 本来格式中时没有这个?号的,代码里面用GBK和utf-8都不能解决. 即使我加了 Str.trim(Str)去除 字符 ...