I - Indoorienteering Gym - 101482I(双向搜索)

2024-04-16 01:18

本文主要是介绍I - Indoorienteering Gym - 101482I(双向搜索),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Lukáš really likes orienteering, a sport that requires locating control points in rough terrain. To entertain the NWERC participants Lukáš wants to organize an orienteering race. However, it would be too harsh for the participants to be outdoors in this cold Swedish November weather, so he decided to jump on the new trend of indoor races, and set the race inside the B building of Linköping University.
Lukáš has already decided on the locations of the control points. He has also decided on the exact length of the race, so the only thing remaining is to decide in which order the control points should be visited such that the length of the total race is as he wishes. Because this is not always possible, he asks you to write a program to help him.
Note from the organizer: the NWERC indoorienteering race for this year has been cancelled since we neglected to apply for an orienteering permit in time from the university administration. (We still need you to solve the problem so that we can organize it for next year.)
Input
The input consists of:
Fredrik and Tommy lost in the B building. Photo by Tommy Olsson. cc-by-sa
• onelinewithtwointegersn(2≤n≤14)andL(1≤L≤1015),thenumberofcontrol points and the desired length of the race, respectively;
• n lines with n integers each. The jth integer on the ith line, dij, denotes the distance betweencontrolpointiandj(1≤dij ≤Lfori̸=j,anddii =0).Forall1≤i,j,k≤N itisthecasethatdij =dji anddij ≤dik +dkj.
Output
Output one line with “possible” if it is possible to visit all control points once in some order and directly return to the first one such that the total distance is exactly L, and “impossible” otherwise.
Sample Input 1 Sample Output 1
4 10 0321 3013 2102 1320
possible
NWERC 2014 Problem I: Indoorienteering
17
Sample Input 2 Sample Output 2
35 012 103 230
impossible

题意:
n个点,点间最短距离给出来了。
求遍历n个点,最后回到起点,其他点只走一次的。
求距离和是否能达到L。

思路:
看了题解,类似双向搜索,拆成一半分别搜。
最后会形成一个环,以0为拆点将环拆成两半,那么0是其中一个环的起点,再分别枚举全排列。

ACNEW

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <set>
#include <queue>
#include <cmath>
#include <vector>
#include <map>
#include <ctime>using namespace std;typedef long long ll;
const int maxn = 20 + 7;ll d[maxn][maxn];
int l[maxn],r[maxn],vis[maxn],l_tmp[maxn],a[maxn];
int cnt,cnt2,cnt3;
vector<ll>R;
ll n,L;void init(int ed) {R.clear();do {ll num2 = 0;for(int i = 2;i <= cnt2;i++) {num2 += d[r[i - 1]][r[i]];}num2 += d[0][r[1]] + d[r[cnt2]][ed];R.push_back(num2);}while(next_permutation(r + 1, r + cnt2 + 1));sort(R.begin(),R.end());
}int Bin(ll x) {return lower_bound(R.begin(),R.end(),x) - R.begin();
}bool Find(ll num) {int pos = Bin(L - num);if(pos < R.size() && R[pos] == L - num) {return true;}return false;
}bool check2(int ed) {do {ll num = d[0][l_tmp[1]] + d[l_tmp[cnt3]][ed];for(int i = 2;i <= cnt3;i++) {num += d[l_tmp[i - 1]][l_tmp[i]];}if(Find(num)) return true;} while(next_permutation(l_tmp + 1,l_tmp + 1 + cnt3));return false;
}bool check() {for(int i = 2;i <= cnt;i++) {cnt3 = 0;init(l[i]);for(int j = 2;j <= cnt;j++) {if(j == i) continue;l_tmp[++cnt3] = l[j];}if(cnt >= 3) {if(check2(l[i])) return true;} else {ll num = d[0][l[i]];if(Find(num)) return true;}}return false;
}int main() {clock_t start_time=clock();scanf("%lld%lld",&n,&L);for(int i = 0;i < n;i++) {for(int j = 0;j < n;j++) {scanf("%lld",&d[i][j]);}}if(n == 2) {if(d[0][1] * 2 != L) {printf("impossible\n");} else {printf("possible\n");}return 0;}int num = (n + 1) / 2;for(int i = 0;i < (1 << n);i++) {cnt = cnt2 = 0;for(int j = 0;j < n;j++) {if(i & (1 << j)) {l[++cnt] = j;} else {r[++cnt2] = j;}}if(cnt == num && l[1] == 0) {if(check()) {printf("possible\n");return 0;}}}printf("impossible\n");clock_t end_time=clock();//    cout<< "Running time is: "<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl;//输出运行时间return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>using namespace std;typedef long double ld;typedef long long ll;const int maxn = 1e5 + 7;
ll d[20][20];
int l[20],r[20];
int num[20];
int lsiz,rsiz;
int n;
ll v[maxn];
int tot;
ll L;bool check(ll val) {if(val <= 0) return false;int pos = lower_bound(v + 1,v + 1 + tot,val) - v;if(v[pos] == val) return true;return false;
}void cal(int s,int e) {tot = 0;do {ll cnt = 0;cnt += d[e][r[1]] + d[r[rsiz]][s];for(int i = 2;i <= rsiz;i++) {cnt += d[r[i - 1]][r[i]];}v[++tot] = cnt;}while(next_permutation(r + 1, r + 1 + rsiz));sort(v + 1,v + 1 + tot);tot = unique(v + 1,v + 1 + tot) - (v + 1);
}bool cal2(int s,int e) {cal(s,e);ll cnt = L;int cur = 0;for(int i = 1;i <= lsiz;i++) {if(l[i] == e || l[i] == s) continue;num[++cur] = l[i];}if(cur) {do {cnt = L;cnt -= d[s][num[1]] + d[num[cur]][e];for(int i = 2;i <= cur;i++) {cnt -= d[num[i - 1]][num[i]];}if(check(cnt)) {return true;}}while(next_permutation(num + 1,num + cur + 1));}else {cnt -= d[e][s];if(check(cnt)) {return true;}}return false;
}bool solve() {for(int i = 2;i <= lsiz;i++) {if(cal2(0,l[i])) return true;}if(lsiz == 1) {if(cal2(0,0)) return true;}return false;
}int main() {scanf("%d%lld",&n,&L);for(int i = 0;i < n;i++) {for(int j = 0;j < n;j++) {scanf("%lld",&d[i][j]);}}if(n == 2) {if(d[0][1] * 2 == L) {printf("possible\n");}else printf("impossible\n");return 0;}int cnt = (1 << n);int flag = 0;for(int i = 1;i < cnt;i++) {lsiz = 0;rsiz = 0;for(int j = 0;j < n;j++) {if(i & (1 << j)) {l[++lsiz] = j;}else {r[++rsiz] = j;}}if(lsiz == n / 2 && l[1] == 0) {if(solve()) {printf("possible\n");flag = 1;break;}}}if(flag == 0) printf("impossible\n");return 0;
}
//4 10
//0 3 2 1
//3 0 1 3
//2 1 0 2
//1 3 2 0

这篇关于I - Indoorienteering Gym - 101482I(双向搜索)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907438

相关文章

C# ComboBox下拉框实现搜索方式

《C#ComboBox下拉框实现搜索方式》文章介绍了如何在加载窗口时实现一个功能,并在ComboBox下拉框中添加键盘事件以实现搜索功能,由于数据不方便公开,作者表示理解并希望得到大家的指教... 目录C# ComboBox下拉框实现搜索步骤一步骤二步骤三总结C# ComboBox下拉框实现搜索步骤一这

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

hdu 4517 floyd+记忆化搜索

题意: 有n(100)个景点,m(1000)条路,时间限制为t(300),起点s,终点e。 访问每个景点需要时间cost_i,每个景点的访问价值为value_i。 点与点之间行走需要花费的时间为g[ i ] [ j ] 。注意点间可能有多条边。 走到一个点时可以选择访问或者不访问,并且当前点的访问价值应该严格大于前一个访问的点。 现在求,从起点出发,到达终点,在时间限制内,能得到的最大

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4277搜索

给你n个有长度的线段,问如果用上所有的线段来拼1个三角形,最多能拼出多少种不同的? import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

【python计算机视觉编程——7.图像搜索】

python计算机视觉编程——7.图像搜索 7.图像搜索7.1 基于内容的图像检索(CBIR)从文本挖掘中获取灵感——矢量空间模型(BOW表示模型)7.2 视觉单词**思想****特征提取**: 创建词汇7.3 图像索引7.3.1 建立数据库7.3.2 添加图像 7.4 在数据库中搜索图像7.4.1 利用索引获取获选图像7.4.2 用一幅图像进行查询7.4.3 确定对比基准并绘制结果 7.