第三次小组例会
大家好!
这段时间强度不是很高做了约莫十八九道题目。。。。。
写了几道题解
1.题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n n n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s s s 和苦度 b b b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
输入格式
第一行一个整数 n n n,表示可供选用的食材种类数。
接下来 n n n 行,每行 2 2 2 个整数 s i s_i si 和 b i b_i bi,表示第 i i i 种食材的酸度和苦度。
输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差
数据规模与约定
对于 100 % 100\% 100% 的数据,有 1 ≤ n ≤ 10 1 \leq n \leq 10 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1 × 1 0 9 1 \times 10^9 1×109,酸度和苦度不同时为 1 1 1 和 0 0 0。
def dfs(n,k,step,flag,v,xuanze):#dfs搜索算法,枚举所有可能的类型
if step==k:
s=[]
for j in range(k):
s.append(v[j])
xuanze.append(s)
if n-flag<k-step:
return#剪枝
for i in range(flag+1,n+1):#避免重复,采用升序
v[step]=i
dfs(n,k,step+1,i,v,xuanze)
n=int(input())
v=[0 for i in range(n)]
shuju=[[0,0]]
xuanze=[]
for i in range(n):
s=list(map(int,input().split()))
s.append(i)
shuju.append(s)
cha=[]
for k in range(1,n+1):
dfs(n,k,0,0,v,xuanze)
for l in xuanze:
suan=1
ku=0
for mm in l:
suan*=shuju[mm][0]
ku+=shuju[mm][1]
cha.append(abs(suan-ku))
a=min(cha)
print(a)
1.涂国旗
题目描述
某国法律规定,只要一个由 N × M N \times M N×M 个小方块组成的旗帜符合如下规则,就是合法的国旗。(毛熊:阿嚏——)
- 从最上方若干行(至少一行)的格子全部是白色的;
- 接下来若干行(至少一行)的格子全部是蓝色的;
- 剩下的行(至少一行)全部是红色的;
现有一个棋盘状的布,分成了 N N N 行 M M M 列的格子,每个格子是白色蓝色红色之一,小 a 希望把这个布改成该国国旗,方法是在一些格子上涂颜料,盖住之前的颜色。
小a很懒,希望涂最少的格子,使这块布成为一个合法的国旗。
输入格式
第一行是两个整数 N , M N,M N,M。
接下来
N
N
N 行是一个矩阵,矩阵的每一个小方块是W
(白),B
(蓝),R
(红)中的一个。
输出格式
一个整数,表示至少需要涂多少块。
样例 #1
样例输入 #1
4 5
WRWRW
BWRWB
WRWRW
RWBWR
样例输出 #1
11
提示
样例解释
目标状态是:
WWWWW
BBBBB
RRRRR
RRRRR
一共需要改 11 11 11 个格子。
数据范围
对于 100 % 100\% 100% 的数据, N , M ≤ 50 N,M \leq 50 N,M≤50。
m,n=map(int,input().split())
a=[]
opop=[]
def create(m,n,w,b,r):#自定义函数,用于生成国旗,w,b,r分别表示白蓝红行的数量
re=[]
for i in range(w):
re.append("W"*n)
for i in range(b):
s="B"*n
re.append(s)
for j in range(r):
rr="R"*n
re.append(rr)
return re
def bijiao(a,BZ,m,n):#用于求出不同元素的数量,即要涂颜色的块数
count=0
for i in range(m):
for j in range(n):
if a[i][j]!=BZ[i][j]:
count+=1
return count
for i in range(m):
sss=input()
a.append(sss)
for j in range(1,m-1):#枚举每种颜色的行数的所有可能
for k in range(1,m-1):
if m-j-k>=1:
BZ=create(m,n,j,k,m-j-k)
opop.append(bijiao(a,BZ,m,n))
print(min(opop))
1.烤鸡
题目背景
猪猪 Hanke 得到了一只鸡。
题目描述
猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10 10 10 种配料(芥末、孜然等),每种配料可以放 1 1 1 到 3 3 3 克,任意烤鸡的美味程度为所有配料质量之和。
现在, Hanke 想要知道,如果给你一个美味程度 n n n ,请输出这 10 10 10 种配料的所有搭配方案。
输入格式
一个正整数 n n n,表示美味程度。
输出格式
第一行,方案总数。
第二行至结束, 10 10 10 个数,表示每种配料所放的质量,按字典序排列。
如果没有符合要求的方法,就只要在第一行输出一个 0 0 0。
样例 #1
样例输入 #1
11
样例输出 #1
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1
提示
对于 100 % 100\% 100% 的数据, n ≤ 5000 n \leq 5000 n≤5000。
这道题属于暴力枚举,做起来好爽
a=[]
n=int(input())
count=0
for q1 in range(1,4):#因为蘸料在1~3克之间,所以直接打表
for q2 in range(1,4):
for q3 in range(1,4):
for q4 in range(1,4):
for q5 in range(1,4):
for q6 in range(1,4):
for q7 in range(1,4):
for q8 in range(1,4):
for q9 in range(1,4):
for q10 in range(1,4):
if q1+q2+q3+q4+q5+q6+q7+q8+q9+q10==n:#符合要求的重量,存储
a.append(str(q1)+" "+str(q2)+" "+str(q3)+" "+str(q4)+" "+str(q5)+" "+str(q6)+" "+str(q7)+" "+str(q8)+" "+str(q9)+" "+str(q10))
count+=1
print(count)
for i in a:
print(i)
贪心算法的初步理解
基本思想:
- 选择最优子问题: 在每一步,贪心算法选择当前状态下的最优解,即局部最优解。
- 不考虑未来: 贪心算法不会回退,不会考虑之后的步骤可能导致的影响,只关注当前步骤的最优解。
特征:
- 局部最优解: 贪心算法做出的每个局部选择都应该是当前状态下的最优选择。
- 无后效性: 在贪心算法中,当前的选择不会影响以后的选择。即,一旦作出决策,就不会再改变。
下面是一道使用贪心算法的题解
最大乘积
题目描述
一个正整数一般可以分为几个互不相同的自然数的和,如 3 = 1 + 2 3=1+2 3=1+2, 4 = 1 + 3 4=1+3 4=1+3, 5 = 1 + 4 = 2 + 3 5=1+4=2+3 5=1+4=2+3, 6 = 1 + 5 = 2 + 4 6=1+5=2+4 6=1+5=2+4。
现在你的任务是将指定的正整数 n n n 分解成若干个互不相同的自然数的和,且使这些自然数的乘积最大。
输入格式
只一个正整数 n n n,( 3 ≤ n ≤ 10000 3 \leq n \leq 10000 3≤n≤10000)。
输出格式
第一行是分解方案,相邻的数之间用一个空格分开,并且按由小到大的顺序。
第二行是最大的乘积。
核心解法:
1.首先,要从2开始分解,这点总显而易见吧
2.然后,要把一个数分的足够多,而且从2之后乘的数要越来越大,才能让最终所得的的乘积最大,不解释了,这是数学问题
3.比如,要求10分解出的最大乘积
从2开始,
sum=2,n=10,start=2
start=2+1=3,sum=5
start=3+1=4,sum=9
start=4+1=5,sum=14
可以看到加到5时sum已近大于10了,放不下了就要拿出来
拿出来多少呢?显而易见,拿出来14-10=4
所以把4拿出来
那么最终分解的数分别是:2,3 ,5
简单吧
下面是代码的实现:
import numpy#NumPy是一个用于进行科学计算的强大库,特别适用于处理大型、多维数组和矩阵,以及执行数学运算。
n=int(input())#获取要分解的数
x=[i for i in range(2,n)]#创建一个列表,列表元素为2到n-1,表示即将用于选择的数
zt=[0 for i in range(2,n)]#表示每一个数的状态,0表示没有被选择,1表示已近选择到的
#例如n=10
#x =[2,3,4,5,6,7,8,9]
#zt=[0,0,0,0,0,0,0,0]初始状态下每个数都还没有被选过
start=2#从2开始
sum1=0#现在得到的和,用于判断和有没有大于n
while sum1<n:
sum1+=start#加上数字
zt[start-2]=1#标记数字被选上
#start=2
#x =[2,3,4,5,6,7,8,9]
#zt=[1,0,0,0,0,0,0,0],表示2被选上了
start+=1#接下来就要加start+1了,迭代
if sum1>n:#如果超出n了
if sum1-n>=2:#表示超出的部分在列表x中,就可以直接从列表中把超出的部分给剪掉
cha=sum1-n#表述超出的部分
zt[cha-2]=0#剪掉
elif sum1-n<2:#表示超出的部分是1,
cha=sum1-n
zt[0]=0#那么就把2去掉,刚才超出了1,现在剪掉了2,那么现在就少了1
zt[start-2]=0
zt[start-2+cha]=1#这两句的意思就是把最后一次加上的数字去掉,然后加上比它大1的那个数,比如去掉4,加上5,这样就不多不少了
count=numpy.count_nonzero(zt)#计算被分解成了多少个数字
#以下为输出部分
k=0
cj=1
for i in range(len(zt)):
if zt[i]!=0:
k+=1
if k!=count:
print(x[i],end=" ")
cj*=x[i]
else:
print(x[i])
cj*=x[i]
break
print(cj)