soj4059 Towns along a Highway解题报告 经典dfs
来源:互联网 发布:nginx 域名绑定 编辑:程序博客网 时间:2024/06/05 12:46
这是11年集训时放的题目,当时深为不解,题目来源是coci。
【大意】
设有n个城镇city[0],city[1],……,city[n-1],city[i]与city[i+1]相邻( i 属于[0,n-2] ),其距离记为dist[i],若给出每两个城市之间的距离,则可以算出任意两个城市间的距离,共有n*(n-1)/2个。
现在给出这n*(n-1)/2个距离,求每两个城市之间的距离,答案可能不存在或者有很多个。
若有多个,则按照dist[i]的字典序输出。n<=20
【分析】
由于n很小,可以考虑搜索算法。
如果枚举相邻2个城市间的距离,则其复杂度为n^(n*(n-1)/2),最大为20^190,完全无法容忍。
其实这道题和论文里的一篇及其相似,关于搜索对象的问题,不同的搜索对象,不同的搜索顺序都极大的影响搜索效率。
这里可以搜索相邻2个城市间的距离,或者第1个城市到第i个城市之间的距离。
先上算法吧:
记sum[i]=dist[0] + ... + dist[i]。
分析知:最大值必为第一个城市到第n个城市间的距离,记为maxLength。
那么第二大的值呢??
显然它为dist[0]+...+dist[n-2]或者dist[1]+...+dist[n-1],否则反证法,第二大的值必然不是dist[0]+...+dist[n-1],故必是dist[0]+...+dist[n-2]或者dist[1]+...+dist[n-1]的一部分(又假设知不是全部),记为dist[i]+..+dist[j],其值显然小于前面两个,但是由于它是第二大的,那么前两个值必然不存在于那任意两个城市间的距离,矛盾,故。。
那么第三大的呢??
类似。。
假设当前最大的没用到的值为k,其中前i个和后j个距离和都算出来了,即已经搜到了sum[0]到sum[i-1]和sum[n+1-j]到sum[n],那么k必然是sum[n-j]或者maxLength-k是sum[i]。
证法同上。
于是其复杂度为O(2^n),搜索深度为n,每个值k有2次向下扩展的机会,故为O(2^n)。
这里注意每次放置的时候将改点到其他已知点的距离都减掉。
附个链接:soj4059
附个代码:
#include <string.h>#include <stdio.h>#include <set>#include <ctype.h>#include <algorithm>#include <queue>#include <string.h>using namespace std;const int maxn = 512 ;int ans[32] , dist[maxn] , cnt[maxn] , end , num[maxn] , myCount[maxn] , top , n , iCount ;vector<int> ve ;struct node { int array[20] ;}hb[maxn*maxn] ;struct cmp { int operator()(const int a,const int b) const { return memcmp(hb[a].array,hb[b].array,sizeof(int)*(n-1)) < 0 ; }};inline bool get(int &t){ bool flag = 0 ; char c; while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ; if( c == -1 ) return 0 ; if(c=='-') flag = 1 , t = 0 ; else t = c ^ 48; while(isdigit(c = getchar())) t = (t << 1) + (t << 3) + (c ^ 48) ; if(flag) t = -t ; return 1 ;}inline int fabs(int x) { return x > 0 ? x : -x ; }void dfs(int);set<int,cmp> st ;void nimei(int pos,int value){ int j , k ; bool sth = true ; for( j = n ; j > pos ; j--) { myCount[cnt[k=fabs(ans[j]-value)]]--; if(myCount[cnt[k]]<0) sth = false ; } if(sth) { ans[pos] = value ; dfs(pos-1); } for( j = n ; j > pos ; j--) myCount[cnt[fabs(ans[j]-value)]]++; }/*59 8 7 6 6 4 3 2 2 1*/void dfs(int pos){ int i ; if( pos == 0 ) { int j = n-1 ; memcpy(hb[iCount].array,ans+1,sizeof(int)*j); sort(hb[iCount].array,hb[iCount].array+j); if( st.count(iCount) == 0 ) st.insert(iCount++); return ; } for ( i = top-1 ; i >= 1 ; i--) if(myCount[i]) break ; if( i < 1 ) return ; nimei(pos,dist[0]-num[i]); nimei(pos,num[i]);}int main(){ int i , j ; myCount[0] = 0 ; while (get(n)&&n>0) { iCount = 0 ; st.clear(); memset(cnt,0,sizeof(cnt)); int maxNum = 0 ; for(i = 0 ; i < n*(n-1)/2 ; i++) { get(dist[i]); cnt[dist[i]]++; } for( i = 1 , top = 1 ; i <= dist[0] ; i++) if(cnt[i]) { num[top] = i ; myCount[top] = cnt[i] ; cnt[i] = top++; } ans[n] = 0 ; ans[n-1] = dist[0] ; myCount[cnt[dist[0]]]--; dfs(n-2); set<int,cmp>::iterator ite = st.begin() ; for( ; ite != st.end() ; ite++) { i = *ite ; printf("%d",hb[i].array[0]); for( j = 1 ; j < n-1 ; j++) printf(" %d",hb[i].array[j]-hb[i].array[j-1]); puts(""); } puts("-----"); }}
- soj4059 Towns along a Highway解题报告 经典dfs
- 百练之Highway解题报告
- MCS_ACM DFS解题报告
- DFS 1253 解题报告
- pku 1691 painting a board dfs+回溯 解题报告
- poj 2488 A Knight's Journey 解题报告 DFS
- DFS——A:N皇后问题 解题报告
- hdu1198解题报告(dfs)
- hdu1224解题报告(dfs)
- poj1154解题报告(dfs)
- A - SnowflakeSnowSnowflakes解题报告
- A - A+B(解题报告)
- POJ1691 Painting A Board ACM解题报告(DFS+构造)难题=。=
- POJ2488/openjudge 1490 A Knight's Journey 解题报告(dfs)
- UVA1615 高速公路(highway)(重庆一中高2018级信息学竞赛测验5) 解题报告
- A+B Coming 解题报告
- USACO A Game解题报告
- 解题报告 codeforces 242A
- [Tomcat6.0源码]从BootStrap的main开始
- javase_23(Http的学习)
- ASP.NET TreeView控件回传问题
- 浅层拷贝和深层拷贝
- java中native关键字的作用
- soj4059 Towns along a Highway解题报告 经典dfs
- XSS攻击
- C++中的静态数据成员的作用与好处
- 【shell】变量
- 经典递归应用--汉诺塔(Java语言版)
- Java关键字static和final
- keil使用详解
- mysql 安装图解
- 非常好用的开机等待(程序)界面类!