T1_挖地雷(提交文件bomp.cpp

递推大法好啊

题解

递推高级题目

这个题就是按照扫雷的思路解决

相邻的三个格子上的雷数和加起来正好等于中间格子上的数

所以当我们确定了第一个格子周围的雷,其余的就都好解决了

注意不好确定的是当第一个格子的数字为1时候,可以在第一个格子上放雷,也可以在第二个格子上放雷,这两种情况可能一种有解,另一种无解

PS:今天这题毒瘤的很,首先谴责T1数据点18:2 1 1,答案不唯一啊!!!

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std; inline int read()
{
int ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=ans*+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} int n;
bool flag;
int pan[];
int ans[]; bool dtdfh()
{
for(int i=;i<=n;i++)
{
ans[i+]=pan[i]-ans[i]-ans[i-];
if(ans[i+]<||ans[i+]>) return ; //超额
} if(ans[n+]>) return ; //不该有数字的位置有了数字
else return ; } int main()
{
freopen("bomp.in","r",stdin);
freopen("bomp.out","w",stdout); n=read();
for(int i=;i<=n;i++)
{
pan[i]=read();
if(pan[i]<||pan[i]>||(i==&&pan[i]>)||(i==n&&pan[i]>)) //输入不合法
{
printf("No answer\n");
return ;
}
} //先确定第一个啊
if(pan[]==) { ans[]=ans[]=; }
if(pan[]==) { ans[]=;ans[]=; }
if(pan[]==) { ans[]=ans[]=; } flag=dtdfh(); //递推求解
if(pan[]==&&flag==)
{
ans[]=;ans[]=;
flag=dtdfh();
} if(!flag) //无解
{
printf("No answer\n");
return ;
} else
{
for(int i=;i<=n;i++)
printf("%d ",ans[i]);
} return ;
}

T2_极值问题(提交文件mn.cpp)

打表大法好啊

题解

我说这题是打表找规律发现是斐波那契数列QWQ

打表之后发现 m , n 是不超过k的两个相邻的最大斐波那契数

正解证明斐波那契,感谢这个大佬 “ 寄蜉蝣于天地,渺沧海之一粟 ”

证明一下啦:

首先我们看到题目给出的那个式子:

start:(n2-mn-m22=1

----> : (m2+mn-n22=1

拿出括号里的单独看:    m2+mn-n

m2+mn-n+2n2-2n2+mn-mn

(m+n)2-2n2-mn

(m+n)-n2-n2-mn

(m+n)-(m+n)n - n2

也就是:(n2-mn-m22  ---->   (m+n)-(m+n)n - n2

so,如果我们有一组解 (m,n),那么一定还存在一组解 (n,m+n),所以你发现这就构成了斐波那契数列!!!

递推求解就好了!!!

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue> using namespace std; inline int read()
{
int ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=ans*+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} const int maxn=1e6+;
int k,m,n;
long long feibo[maxn]={,}; int main()
{
freopen("mn.in","r",stdin);
freopen("mn.out","w",stdout);
k=read(); for(int i=;i<=;i++)
{
feibo[i]=feibo[i-]+feibo[i-];
} for(int i=;i<=;i++)
{
if(feibo[i]>k) {
m=i-;
n=i-;
printf("%ld %ld\n",feibo[n],feibo[m]);
return ;
}
} return ;
}

T3_15数码问题(提交文件Puzzle15.cpp)

骗分大法好啊

题解

说人话:编程50步求解15数码

这题数据水,偏分最高60

what is UVA???一个nice的oj

这个题目用到了神奇的 IDA* 算法(崩溃)

感谢百度找到一个大佬--恋恋恋恋吥舍--

链接: 原文:https://blog.csdn.net/baidu_30476939/article/details/53119195

首先了解一下几个概念:

1.逆序对:在一个序列里,如果一个数后面的数比他小,那么他们两个构成一个逆序对

有何用处??判断一下有无解:

把初始矩阵从左到右,从上到下,展成一行,求它的逆序对 (显然目标矩阵的逆序对个数为0)

           于是这里用到一个定理:设初始状态0所在的行数为i,目标状态0所在的行数为j,两者之差的绝对值为k。若k为奇数,则初始矩阵与目标矩阵两个矩阵相应的逆序数的奇偶性相异才有解。若k为偶数,则两个矩阵的逆序数必须相同才有解。不是上述两种情况即为无解。通过初始判定就可以不用搜索就能直接否定无解情况。


转化到这个题上就是,K为奇数,矩阵逆序对数也应为奇数,K为偶数,矩阵逆序对数也应为偶数

2.曼哈顿距离:坐标系中两点  横坐标之差的绝对值+纵坐标的绝对值  之和

有何用处:预估最少步数,预估出来的步数一定是小于等于实际步数的

官方一点就是:求出初始矩阵与目标矩阵对应值得曼哈顿距离并求和(除去0)得到的值为评估值,写成函数即为评估函数。该值为从初始状态到目标状态所要经过的最小步数,实际步数只会大于等于该值。

算法介绍:

这次使用的算法是IDA*。我们首先是用逆序数进行判定是否有解,有解才进行搜索。有解的话,则先得到评估函数的初始值,该值为最小步数,递归深度(步数)必然大于等于这个初始值limit。我们先按深度搜索寻遍该深度的所有情况,看是否能找到解,有解则该解是最优解。若没解,则将深度的限制条件limit加1,再次递归下一层深度的所有情况,有解即为最优解,无解则继续将深度限制条件limit加1,这样不停循环直到某个深度maxLevel,则放弃寻找,因为在maxLevel步中没有找到,继续找下去时间花销太高,故放弃寻找。这就是IDA*中ID的意思,迭代加深。其中,算法在递归中使用了当前递归深度level,用level+评估函数(当前状态到目标状态至少需要的步数)<=limit作为剪枝条件,不满足该条件的在该分支上肯定无解。这样我们就可以找到在maxLevel步以内的最优解。

代码

//15数码问题
#include<iostream>
#include<cstdlib>
#include<cmath>
#define size 4
using namespace std; int move[][]={{-,},{,-},{,},{,}};//上,左,右,下增量
char op[]={'U','L','R','D'};
int map[size][size],map2[size*size],limit,path[];
//limit预估最少步数
int flag,length;
//int goal_st[3][3]={{1,2,3},{4,5,6},{7,8,0}};//目标状态
//goal存储目标位置,即0存在(3,3),1存在(0,0)...
int goal[][]= {{,},{,},{,}, {,},
{,},{,},{,}, {,},
{,},{,},{,}, {,},
{,},{,},{,}, {,}}; int h(int a[size*size])//求逆序数 ,判断有无解
{
int i,j,num,w,x,y; //w记录起点标号
num=; //逆序对数
for(i=;i<size*size;i++)
{
if(a[i]==)
w=i;
for(j=i+;j<size*size;j++)
{
if(a[i]>a[j])
num++;
}
} x=w/size; //起点横坐标
y=w%size; //起点纵坐标 num+=abs(x-)+abs(y-); //9102.9.7 if(num%==)
return ;
else
return ;
} int manhattan(int a[][size])//计算曼哈顿距离,小等于实际总步数
{
int i,j,cost=;
for(i=;i<size;i++)
for(j=;j<size;j++)
{
int w=map[i][j];
cost+=abs(i-goal[w][])+abs(j-goal[w][]);
}
return cost;
} void swap(int*a,int*b)
{
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
} void dfs(int sx,int sy,int dep,int pre_move)//sx,sy是空格的位置
{
int i,j,nx,ny;
if(flag)
return;
int dv=manhattan(map);
if(dep==limit)
{
if(dv==)
{
flag=;
length=dep;
return;
}
else
return;
}
else if(dep<limit)
{
if(dv==)
{
flag=;
length=dep;
return;
}
}
for(i=;i<;i++)//4个方向尝试
{
if(i+pre_move==&&dep>)//不和上一次移动方向相反,对第二步以后而言
continue;
nx=sx+move[i][];
ny=sy+move[i][];
if(<=nx && nx<size && <=ny&&ny<size)//如果可以移动
{
swap(&map[sx][sy],&map[nx][ny]);//交换两位置
int p=manhattan(map);
if(p+dep<=limit&&!flag)
{
path[dep]=i;
dfs(nx,ny,dep+,i);
if(flag)
return;
}
swap(&map[sx][sy],&map[nx][ny]);
}
}
} int main()
{
freopen("Puzzle15.in","r",stdin);
freopen("Puzzle15.out","w",stdout);
int i,j,k,l,m,n,sx,sy;
char c,g;
i=;
scanf("%d",&n);
while(n--) //n组数据
{
flag=;length=;
//flag判断有无解 memset(path,-,sizeof(path));
//路径存储数组,记录每一步的抉择,也就是最后要输出的答案
//(数字代码,后边转化成字符串) for(i=;i<;i++)
{
scanf("%d",&map2[i]); //读入15数码图
if(map2[i]==) //寻找0在哪里
{
map[i/size][i%size]=; //记录在图上的位置
sx=i/size;sy=i%size; //记录起点的横纵坐标
}
else
{
map[i/size][i%size]=map2[i]; //记录到图上
}
} if(h(map2)==)//该状态可达
{
limit=manhattan(map);
while(!flag&&length<=)//题中要求50步之内到达
{
dfs(sx,sy,,);
if(!flag)
limit++; //得到的是最小步数
}
if(flag)
{
for(i=;i<length;i++)
printf("%c",op[path[i]]);
printf("\n");
}
}
else if(!h(map2)||!flag)
printf("This puzzle is not solvable.\n");
}
return ;
}

-----在崩溃的边缘疯狂试探-----

最新文章

  1. 自动完成--autoComplete插件
  2. 【转】CentOS 6.5安装pyspider过程记录
  3. Unity 坐标系
  4. 重学STM32----(一)
  5. JasperReports+iReport打印为excel表头重复问题解决
  6. MenuDrawer的使用
  7. 【HDOJ】3518 Boring Counting
  8. Raid1源代码分析--读流程
  9. bat自动创建文件夹(以当前时间命名)
  10. CentOS7搭建时间服务器-chrony(不坑)
  11. 《深入理解Java虚拟机》学习笔记(一)
  12. MySQL 各类数据文件介绍
  13. .net core支持的操作系统版本
  14. mycat高可用集群搭建
  15. JQuery 分割字符串
  16. PHP判断{函数/类/方法/属性}是否存在
  17. 一:Maven知识整理
  18. Cesium.js点击事件
  19. 消费者用nginx做负载均衡,提供者用zookeeper自带功能实现负载均衡
  20. URAL 2062 树状数组

热门文章

  1. vue记录错误和警告日志
  2. eclipse导入myeclipse中的项目(如何把Webroot改为WebContent)
  3. Linux Exploit系列之一 典型的基于堆栈的缓冲区溢出
  4. 搭建内部NuGet服务
  5. java执行字符串中的运算公式
  6. server version for the right syntax to use near &#39;USING BTREE 数据库文件版本不合导致的错误
  7. 【模板】manachar
  8. 希尔排序java代码
  9. 微信小游戏egret开发包括p2引擎小结
  10. Pandas的常见使用方法操作