目录
一.问题叙述
N只小猪排成一个队列在沿河的公路上飞驰。现有n个入口,第i个入口唯一对应河对岸的第j个出口。小猪队列在经过第i个入口时可以选择过河与否,若选择过河,则队首的一只小猪去到对岸第j个出口。要求经过了n个入口后,河对岸小猪的相对顺序与原队列相同(倒序)。求最大过河小猪数。
如图:输入为(4,2,6,1,3,5)表示第一个入口对应第4个出口,第二个入口对应第二个入口,等等。
情况1表示,选择了所有入口进入,导致河对岸的小猪相对顺序与原队列不同。
情况2表示,只选择了2,5,6号入口进入,河对岸小猪的相对顺序与原队列相同,同时河对岸小猪数量最大。(在4,5,6号入口进入也是3)
输入:第一行为正整数t,表示t个测试用例。之后t行,每行m<20000个正整数,其中第i个正整数j表示第i个入口对应第j个出口。
输出:每个用例输出一行,该行有一个正整数,表示最大河对岸小猪数。
样例:
输入:
3
4 2 6 1 3 5
1 2 3 4 5 6 7
8 7 6 5 4 3 2 1
2 8 1 5 6 4 3 8 9
输出:
3
7
1
5
二.研究报告
三.项目代码
from collections import defaultdict
A=defaultdict(list)
def read_file(filepath,A):
""""处理数据"""
f=open(filepath,"r")
test_num=int(f.readline().strip())
for i in range(test_num):
mid=[]
for line in f.readline().split():
A[i].append(int(line))
return test_num
def erfenchazhao(data,left,right,key):
"""二分查找+返回替换位置"""
if((right-left)==1):#data长度为1,直接返回
if(data[left]>=key):
return left
else:
mid=(left+right)//2
if key<data[mid] and key>data[mid-1] and mid>=1:#找到在data(递增)中比第一个自己大的元素的位置返回
return mid
else:
if key<data[mid]:
return erfenchazhao(data,left,mid,key)
else:
return erfenchazhao(data,mid+1,right,key)
def answer_problem(testdata):
"""动态规划+二分查找-求解"""
B=[]#B[i-1]存储最长上升子序列为i序列的最小的最末元素
B.append(testdata[0])
for i in range(len(testdata)):
if(testdata[i]>B[-1]):#比此时B的最后一个元素大,就加入
B.append(testdata[i])
else:#否则就二分而查找,找到第一个比自己小的元素
index=erfenchazhao(B,0,len(B),testdata[i])
B[index]=testdata[i]
return len(B)
num=read_file('project7-test1',A)
for i in range(num):
ans=answer_problem(A[i])
print(ans)