充实的寒假生活(GREEDY/DP)
描述
寒假马上就要到了,龙傲天同学获得了从第0天开始到第60天结束为期61天超长寒假,他想要尽可能丰富自己的寒假生活。 现提供若干个活动的起止时间,请计算龙同学这个寒假至多可以参加多少个活动?注意所参加的活动不能有任何时间上的重叠,在第x天结束的活动和在第x天开始的活动不可同时选择。
输入
第一行为整数n,代表接下来输入的活动个数(n < 10000) 紧接着的n行,每一行都有两个整数,第一个整数代表活动的开始时间,第二个整数代表全结束时间
输出
输出至多参加的活动个数
样例输入
5
0 0
1 1
2 2
3 3
4 4
样例输出
5
解决
class Solution(object):
def eraseOverlapIntervals(self, intervals):
"""
:type intervals: List[List[int]]
:rtype: int
"""
if not intervals or len(intervals) == 0:
return 0
intervals.sort(key = lambda x: x[0]) # 按左端点从小到大排序
temp_pos = 0
cnt = 0
for i in range(1, len(intervals)):
if intervals[temp_pos][1] >= intervals[i][0]: # 当当前区间右端点>i区间左端点
if intervals[i][1] < intervals[temp_pos][1]: # 当i区间右端点<当前区间右端点,表示i区间被覆盖在当前区间中
temp_pos = i # 更新temp_pos,选择覆盖范围小的i区间
cnt += 1 # 当前区间右端点>i区间左端点都要计数+1
else:
temp_pos = i # 当当前区间右端点<=i区间左端点,表示不重叠,要更新temp_pos
return len(intervals)-cnt
if __name__ == "__main__":
n=int(input())
intervals=[]
for i in range(n):
intervals.append(list(map(int, input().split())))
print(Solution().eraseOverlapIntervals(intervals))
和为给定数
描述
给出若干个整数,询问其中是否有一对数的和等于给定的数。
输入
共三行: 第一行是整数n(0 < n <= 100,000),表示有n个整数。 第二行是n个整数。整数的范围是在0到108之间。 第三行是一个整数m(0 <= m <= 230),表示需要得到的和。
输出
若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。若找不到符合要求的数对,输出一行No。
样例输入
4
2 5 1 4
6
样例输出
1 5
解决
def find(key,base,top): #二分查找
while base<=top:
mid = (base+top)//2
if a[mid]==key:
return True
elif a[mid]<key:
base=mid+1
else:
top=mid-1
return False
n=int(input())
a=list(map(int,input().split()))
a=sorted(a)
flag=0
# print(a)
m=int(input())
for i in range(n):
key=m-a[i]
base=i+1
top=n-1
if find(key,base,top):
print(a[i],key)
flag=1
break
if flag==0:
print("No")
求逆序对数
描述
对于一个长度为N的整数序列A,满足i < j且 Ai > Aj.的数对(i,j)称为整数序列A的一个逆序
请求出整数序列A的所有逆序对个数
输入
输入包含多组测试数据,每组测试数据有两行
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列
输出
每组数据对应一行,输出逆序对的个数
样例输入
5
1 2 3 4 5
5
5 4 3 2 1
1
1
0
样例输出
0
10
0
解决1
冒泡,可能会超时
def main():
while True:
n = int(input())
if n==0:
return
ll = list(map(int, input().split()))
# print(ll)
c=[0 for i in range(101)]
group=0
for i in range(n-1):
for j in range(i,n-1):
if ll[j]>ll[j+1]:
group+=1
print(group)
if __name__ == '__main__':
main()
解决2
归并
def merge_sort(a):
s = 0
if len(a) <= 1: return 0
mid = len(a) // 2
l = a[:mid]
r = a[mid:]
s += merge_sort(l) + merge_sort(r)
i = j = k = 0
while (i < len(l) and j < len(r)):
if (l[i] <= r[j]):
a[k] = l[i]
i += 1
k += 1
else:
a[k] = r[j]
j += 1
k += 1
s += len(l) - i
while (i < len(l)):
a[k] = l[i]
i += 1
k += 1
while (j < len(r)):
a[k] = r[j]
j += 1
k += 1
return s
def main():
while True:
n = int(input())
if n==0:
return
ll = list(map(int, input().split()))
print(merge_sort(ll))
if __name__ == '__main__':
main()
小木棍
描述
小明将一批等长的木棍随机切成最长为50单位的小段。现在他想要将木棍还原成原来的状态,但是却忘记了原来的木棍数量和长度。请写一个程序帮助他计算如果还原成原来的等长木棍,其长度可能的最小值。所有的长度均大于0。
输入
输入包含多个实例。每个实例有两行,第一行是切割后的木棍数量n(最多64个),第二行为n个以空格分开的整数,分别为每根木棍的长度。输入的最后以n为 0 结束。
输出
对于每个实例,输出一行其长度的可能的最小值。
样例输入
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
样例输出
6
5
来源
来自计算概论B期末考试,本题对数据进行了弱化
解决
N=105
a=[0 for _ in range(N)]
v=[0 for _ in range(N)]
target=0
n=0
maxn=0
def dfs(cnt, len, pos):
if cnt == target:
return True #拼够了根数,符合题意
if len == maxn:
return dfs(cnt+1, 0, 0) #拼完了一根 继续下一根
i = pos
while i<n:
if v[i]==0 and len+a[i]<=maxn:
v[i]=1
if dfs(cnt, len+a[i], i):
return True
v[i]=0
if len == 0:
return False #凑第一根的时候可以随便选,如果随便选都凑不成一根,那这个长度不行 神奇剪枝!!
while i+1<n and a[i+1]==a[i]:
i += 1 #如果用当前的小木段拼凑 失败则与它等长的同样失败,小剪枝
i += 1
return False
while True:
n=int(input())
if n==0:
break
arr = input()
a = [0 for _ in range(N)]
a = [int(n) for n in arr.split()]
asum = 0
asum = sum(a)
a=sorted(a,reverse=True)
maxn = 0
maxn=a[0]
while maxn <= asum:
if asum%maxn == 0:
target = asum / maxn
v = [0 for _ in range(N)]
if dfs(0, 0, 0):
break
maxn += 1
print(maxn)
修仙之路
描述
修仙之路长漫漫,逆水行舟,不进则退!你过五关斩六将,终于来到了仙界。仙界是一个r行c列的二维格子空间,每个单元格是一个”境界“,每个境界都有等级。你需要任意选择其中一个境界作为起点,从一个境界可以前往上下左右相邻四个境界之一 ,当且仅当新到达的境界等级增加。你苦苦行走,直到所在的境界等级比相邻四个境界的等级都要高为止,一览众山小。请问包括起始境界在内最长修仙路径需要经过的境界数是多少?
输入
第一行为两个正整数,分别为r和c(1<=r,c<=100)。 接下来有r行,每行有c个0到100000000之间的整数,代表各境界的等级。
输出
输出一行,为最长修仙路径需要经过的境界数(包括起始境界)。
样例输入
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
样例输出
25
解决1
没有考虑位于边界的“仙境”
import java.util.Scanner;
/**]
*
* 5 5
* 1 2 3 4 5
* 16 17 18 19 6
* 15 24 25 20 7
* 14 23 22 21 8
* 13 12 11 10 9
*
*
*/
public class Main {
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
int m= sc.nextInt();
int n =sc.nextInt();
int [][] nums = new int[m][n];
for(int i=0;i<m;i++){
for(int j = 0;j<n;j++){
nums[i][j] = sc.nextInt();
}
}
/* int [][] dp = new int[m][n];
dp[0][0] =1;
int target =0;
// i+1,j // i-1,j // i,j+1// i,j-1
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(i==0&&j==0){
continue;
}
if(i+1<m&&j<n && nums[i+1][j]<nums[i][j]){
dp [i][j] =Math.max(dp[i+1][j],dp[i][j])+1;
}
if (0<=i-1&&j<n&& nums[i-1][j]<nums[i][j]){
dp [i][j] =Math.max(dp[i-1][j],dp[i][j])+1;
}
if(i<m&&j+1<n && nums[i][j+1]<nums[i][j]){
dp [i][j] =Math.max(dp[i][j+1],dp[i][j])+1;
}
if(i<m&&j-1>=0 && nums[i][j-1]<nums[i][j]){
dp [i][j] =Math.max(dp[i][j-1],dp[i][j])+1;
}
int tmp = nums[i][j];
int tmp1 = dp[i][j];
target = Math.max(dp[i][j],target);
}
}
System.out.println(target);
*/
int a = dfs(nums,0,0,m,n,1);
System.out.println(a);
}
public static int dfs(int [][] nums ,int i,int j ,int m, int n ,int tt ){
if(i<0 || i>m || j<0||j>n){
return 0;
}
if(is(nums,i,j,m,n)==4){
return tt;
}
int a =0;
int b=0;
int c=0;
int d=0;
if(i-1>=0&&nums[i][j]<nums[i-1][j]){
a= dfs(nums, i-1, j, m, n,tt+1);
}
if(i+1<m&&nums[i][j]<nums[i+1][j]){
b= dfs(nums, i+1, j, m, n,tt+1);
}
if(j-1>=0&&nums[i][j]<nums[i][j-1]){
c= dfs(nums, i, j-1, m, n,tt+1);
}
if(j+1<n&&nums[i][j]<nums[i][j+1]){
d= dfs(nums, i, j+1, m, n,tt+1);
}
a= Math.max(a,b);
a= Math.max(a,c);
a= Math.max(a,d);
return a;
}
public static int is(int [][] nums,int i,int j,int m,int n){
int tar=0;
if(i-1>=0){
if( nums[i][j]>nums[i-1][j]){
tar++;
}
}
if(i+1<m){
if( nums[i][j]>nums[i+1][j]){
tar++;
}
}
if(j-1>=0){
if( nums[i][j]>nums[i][j-1]){
tar++;
}
}
if(j+1<n){
if( nums[i][j]>nums[i][j+1]){
tar++;
}
}
return tar;
}
}
来自啊鱼咕嘟
解决2
# 5 5
# 1 2 3 4 5
# 16 17 18 19 6
# 15 24 25 20 7
# 14 23 22 21 8
# 13 12 11 10 9
n,m=map(int,input().split())
nums = []
for _ in range(n):
nums.append(list(map(int, input().split())))
dp=[[-1]* m for _ in range(n)]
move=[[0,1],[1,0],[-1,0],[0,-1]]
def dfs(i,j):
if dp[i][j]!=-1:
return dp[i][j]
ret=1
for oi,oj in move:
ni,nj=i+oi,j+oj
if 0<=ni<n and 0<=nj<m and nums[i][j]>nums[ni][nj]:
ret=max(ret,dfs(ni,nj)+1)
dp[i][j]=ret
return dp[i][j]
res=0
for i in range(n):
for j in range(m):
res=max(res,dfs(i,j))
print(res)
拦截导弹
描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹。
输入
第一行是一个整数N(不超过15),表示导弹数。 第二行包含N个整数,为导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数)。
输出
一个整数,表示最多能拦截的导弹数。
样例输入
8
389 207 155 300 299 170 158 65
样例输出
6
解决
i=0
data = [0 for _ in range(100)]
ans = [0 for _ in range(100)]
n=int(input())
arr=input()
data = [int(n) for n in arr.split()]
ans[0] = 1
maxt = 1
for j in range(1, n):
ans[j] = 1
for i in range(0, j):
if data[i]>=data[j]:
if ans[i]+1> ans[j]:
ans[j] = ans[i]+1
if ans[j]> maxt:
maxt = ans[j]
print(maxt)
采药(DP)
描述
辰辰是个很有潜能、天资聪颖的孩子,他的梦想是称为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
输入
输入的第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出
输出只包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
样例输入
70 3
71 100
69 1
1 2
样例输出
3
来源
NOIP 2005
解决
N=1010
T,M=map(int,input().split())
f = [0 for _ in range(N)]
for i in range(0, M):
v,w=map(int,input().split())
for j in range(T, v - 1, -1):
f[j] = max(f[j], f[j - v] + w)
print(f[T])
简单的整数划分问题
描述
将正整数n 表示成一系列正整数之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。 正整数n 的这种表示称为正整数n 的划分。正整数n 的不同的划分个数称为正整数n 的划分数。
输入
标准的输入包含若干组测试数据。每组测试数据是一个整数N(0 < N <= 50)。
输出
对于每组测试数据,输出N的划分数。
样例输入
5
样例输出
7
提示
5, 4+1, 3+2, 3+1+1, 2+2+1, 2+1+1+1, 1+1+1+1+1
解决
def f(x,y):
if y == 1:
return 1
elif y <= 0:
return 0
elif x < y:
return 0
else:
return(f(x - 1,y - 1) + f(x - y,y))
while True:
try:
n = int(input())
s = 1
for i in range(n):
s = s + f(n,i)
print(s)
except EOFError: break