算法竞赛入门第七章:竞赛选讲(Uva12325,Uva1603)
来源:互联网 发布:centos命令大全 编辑:程序博客网 时间:2024/05/18 02:11
宝箱Uva12325:
这道题很有思维强度,首先比较容易想到的是枚举宝箱的数量,从0到[n/s1]或者0到[n/s2]。但是由于输入很大,当s1,s2都很小的时候,那么枚举的数量将会非常的巨大。因此针对s1,s2较小而n很大的情况,需要提供另一种思路。
另一种枚举的思路是从s1,s2入手的。因为s1,s2很小,如果枚举的数量和他们成正相关,那么就可以确保枚举的效率。考虑一个事实:s1个宝物1和s2个宝物2是同样的体积,那么对于任意的宝物s1个宝物1和任意的s2个宝物2,我们总可以相互替换。只需要比较s2*v1与s1*v2的大小,就可以确定某一个宝物至多只能取s1-1或s2-1种,否则就可以相互替换。这样枚举的数量就限制在min(s1-1,s2-1,[N/s1],[N/s2])中了。
def solve(n,s1,v1,s2,v2): max_v = 0 def recur_search(s1,v1,s2,v2): nonlocal max_v for k1 in range(0,n//s1+1): remain = n-k1*s1 k2 = remain//s2 max_v = max(max_v,k1*v1+k2*v2) def search_2(s,s1,v1,s2,v2): nonlocal max_v for k1 in range(0,s+1): remain = n-k1*s1 k2 = remain//s2 max_v = max(max_v,k1*v1+k2*v2) if n//s1<10000:recur_search(s1,v1,s2,v2) elif n//s2<10000:recur_search(s2,v2,s1,v1) elif s2*v1<s1*v2:search_2(s2-1,s1,v1,s2,v2) else:search_2(s1-1,s2,v2,s1,v1) print(max_v)
Uva1374 使用IDA*算法效率会高一点。如果使用BFS效率将会非常低。对于队列,可能取元素和放元素比for循环要慢很多,其次,对于由于BFS很难进行剪枝,因为很多元素会重复计算,最后,判重的时候注意需要对状态进行排序,否则会造成状态的重复。但是排序,添加就需要很多的时间。
另外IDA*的一个好处是不需要在最后一次迭代中展开整个解答树。
(1) 尽量先拿两个较大的数先加再减,这样可以尽快接近目标。
(1) 总是使用最新得到的元素进行操作。
def solve(n): def dfs(d,state): nonlocal ok,max_d if d==max_d: if n in state:ok = True; return u = max(state) if u<<(max_d-d)<n:return for op in [1,-1]: for j in range(d,-1,-1): next = state[d]+op*state[j] if next<=0 or next in state:continue if u>n and next>n:continue state[d+1] = next dfs(d+1,state) if ok:return max_d = 0 ok = False for max_d in range(1,20): ok = False dfs(0,[1]+[0]*(max_d)) print(max_d) if ok:print(max_d,);break
BFS的代码
def solve_3(n): def bfs(): state = deque() vsit = set() vsit.add((1,)) state.append((1,)) while len(state[-1]): now = state.popleft() if n in now:return len(now) for i in range(len(now)-1,-1,-1): for op in [1,-1]: next=tuple(sorted(now+(now[-1]+now[i]*op,))) if next not in vsit and next[-1]>0 and next[-1] not in now: vsit.add(next) state.append(next) print(bfs()-1)
Uva1603 这道题有一定难度,关键是要想到如何将正方形和边联系到一起。注意,我们以正方形作为搜索对象,然后将边存在正方形里面。我们将每一个可能的正方形都进行编号然后存储它们的边数,以及相关联的边(即时该正方形已经被去掉边了)。这样我们从小正方形开始,因为小正方形被破坏之后大的正方形也可能会被破坏掉,这样就减少许多节点。
(1) 如果我们将每一个正方形都动态的维护起来,那么编程上可能会比较繁琐,特别是在搜索时要维护正方形的状态。因此就干脆只维护固定的正方形,然后再判断该正方形是不是完全正方形。
(2) 可以进行剪枝,注意这样一个事实,如果当前的边里面最多的一个关联到x个正方形,那么后面的最理想的情况是每一次都可以减少x,则(maxd-d)*x
def solve(n,missing): def row_match(x,y): return (2*n+1)*x+y def col_match(x,y): return (2*n+1)*x+y+n def init(): for v in missing:exists[v-1] = 0 remains,maxsize = 0,60 exists,matches = [1]*2*n*(n+1),[[] for i in range(2*n*(n+1))] size,fullsize = [0]*maxsize,[0]*maxsize contains = {} s = 0 init() for L in range(1,n+1): for x in range(0,n-L+1):#x from 0,n-L for y in range(0,n-L+1):#y from 0,n-L contains[s] = set() fullsize[s] = 4*L for j in range(0,L):#j from 0,L-1 up = row_match(x,y+j) down = row_match(x+L,y+j) left = col_match(x+j,y) right = col_match(x+j,y+L) e = [up,down,left,right] for t in e: contains[s].add(t) matches[t].append(s) size[s] += exists[up]+exists[down]+exists[left]+exists[right] if size[s]==fullsize[s]:remains+=1 s+=1 def find_square(): for i in range(s): if size[i]==fullsize[i]:return i return -1 def process_edge(): for i,x in enumerate(matches): num = 0 for squ in x: if size[squ]==fullsize[squ]:num+=1 matches[i] = num def dfs(d,remains): nonlocal maxd,s,ok if d==maxd: if find_square()==-1:ok = True return most_destroyed = max(matches) if (maxd-d)*most_destroyed < remains:return k = find_square() for edge in contains[k]: for j in range(s): if edge in contains[j]: if size[j]==fullsize[j]: remains -= 1 matches[edge]-=1#square j is complete size[j] -= 1 dfs(d+1,remains) if ok:return for j in range(s): if edge in contains[j]: if size[j]==fullsize[j]: remains +=1 matches[edge]+=1#the square j is complete size[j] += 1 ok = False process_edge() for maxd in range(1,n*n): ok = False dfs(0,remains) print(maxd) if ok:print(maxd);break
dfs法,相对来说效率会慢一些。因为第一次的搜索可能会搜到一个比较深的解,那么后来的优化剪枝就相对比较低效。
def solve(n,missing): def row_match(x,y): return (2*n+1)*x+y def col_match(x,y): return (2*n+1)*x+y+n def init(): for v in missing:exists[v-1] = 0 remains,maxsize = 0,60 exists,matches = [1]*2*n*(n+1),[[] for i in range(2*n*(n+1))] size,fullsize = [0]*maxsize,[0]*maxsize contains = {} s = 0 init() for L in range(1,n+1): for x in range(0,n-L+1):#x from 0,n-L for y in range(0,n-L+1):#y from 0,n-L contains[s] = set() fullsize[s] = 4*L for j in range(0,L):#j from 0,L-1 up = row_match(x,y+j) down = row_match(x+L,y+j) left = col_match(x+j,y) right = col_match(x+j,y+L) e = [up,down,left,right] for t in e: contains[s].add(t) matches[t].append(s) size[s] += exists[up]+exists[down]+exists[left]+exists[right] if size[s]==fullsize[s]:remains+=1 s+=1 def find_square(): for i in range(s): if size[i]==fullsize[i]:return i return -1 def process_edge(): for i,x in enumerate(matches): num = 0 for squ in x: if size[squ]==fullsize[squ]:num+=1 matches[i] = num def dfs_1(d,remains): nonlocal best if d>= best:return most_destroyed = max(matches) if (best-d)*most_destroyed < remains:return k = find_square() if k==-1:best=d;print(best);return for edge in contains[k]: for j in range(s): if edge in contains[j]: if size[j]==fullsize[j]: remains -= 1 matches[edge]-=1#square j is complete size[j] -= 1 dfs_1(d+1,remains) for j in range(s): if edge in contains[j]: size[j] += 1 if size[j]==fullsize[j]: remains +=1 matches[edge]+=1#the square j is complete process_edge() print(matches) ok = False best = n*n dfs_1(0,remains) print(best)
0 0
- 算法竞赛入门第七章:竞赛选讲(Uva12325,Uva1603)
- 算法竞赛入门第五章(竞赛题目选讲)解析:
- 算法竞赛入门第三章竞赛题目选讲
- 算法竞赛入门第七章:习题
- 算法竞赛入门第七章(1):暴力枚举
- 算法竞赛入门第七章(2):枚举排列和子集
- 算法竞赛入门第七章:回溯与路径寻找
- 算法竞赛入门第七章:迭代加深搜索
- 算法竞赛入门经典-刘汝佳-第七章暴力
- 算法竞赛入门经典第6章图论和树:竞赛选讲部分与习题
- 算法竞赛入门经典
- 算法竞赛入门经典
- 《算法竞赛入门》读书笔记
- 算法竞赛入门学习
- README: 算法竞赛入门
- 算法竞赛入门---洪水
- 算法竞赛入门
- 算法竞赛入门经典第七章暴力求解法7.1节第一题
- 为什么不应该使用ZooKeeper做服务发现
- 机器学习/深度学习/自然语言处理学习路线
- win10杜比音效安装教程以及资源
- 如何创建SSH Keys(Git)
- 工作期间常用的linux命令
- 算法竞赛入门第七章:竞赛选讲(Uva12325,Uva1603)
- 关于HCA卡的node guid 和port guid
- Android的onCreateOptionsMenu()创建菜单Menu详解
- 进程保活
- Unity3D开发为什么C#语言学习叫苦连连
- Python 深入剖析SocketServer模块(二)(V2.7.11)
- python中if __name__ == '__main__': 的解析
- unity3d ArgumentException: The Assembly System.Configuration is referenced by System.Data.
- SQL注入