0%

exercise6:装饰器的使用

user-credentials.txt内容

1
2
3
4
{"name":"xiaoming", "password":"123"}
{"name":"xiaowang", "password":"321"}
{"name":"xiaofang", "password":"432"}
{"name":"xiaobai", "password":"111"}

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import json

def read_user_credentials(file_path):
credentials = []
with open(file_path, 'r') as file:
for line in file:
user_info = json.loads(line.strip())
credentials.append(user_info)
return credentials

def authentication_required(func):
authenticated = False

def wrapper(*args, **kwargs):
nonlocal authenticated
if not authenticated:
username = input("Enter your username: ")
password = input("Enter your password: ")
user_credentials = read_user_credentials("user_credentials.txt")
for user_info in user_credentials:
if user_info.get('name') == username and user_info.get('password') == password:
authenticated = True
print("Authentication successful!")
break
else:
print("Authentication failed. Please try again.")
return
return func(*args, **kwargs)

return wrapper

@authentication_required
def function1():
print("This is function 1.")

@authentication_required
def function2():
print("This is function 2.")

if __name__ == "__main__":
function1()
function1()

output

1
2
3
4
5
6
Enter your username: xiaoming
Enter your password: 123
Authentication successful!
This is function 1.
This is function 1.

题目

地图上有 N 个目标,用整数 Xi,Yi , 表示目标在地图上的位置,每个目标都有一个价值 Wi 。

注意:不同目标可能在同一位置。

现在有一种新型的激光炸弹,可以摧毁一个包含 R×R个位置的正方形内的所有目标。

激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆炸范围,即那个正方形的边必须和 x,y 轴平行。

求一颗炸弹最多能炸掉地图上总价值为多少的目标。

## 输入格式

第一行输入正整数 N 和 R ,分别代表地图上的目标数目和正方形包含的横纵位置数量,数据用空格隔开。

接下来 N 行,每行输入一组数据,每组数据包括三个整数 Xi,Yi,Wi , , ,分别代表目标的 x 坐标,y 坐标和价值,数据用空格隔开。

## 输出格式

输出一个正整数,代表一颗炸弹最多能炸掉地图上目标的总价值数目。

## 数据范围

\(0≤R≤10^9\) \(0<N≤100000\) \(0≤Xi,Yi≤50000\) \(0≤Wi≤10000\)

## 输入样例:

1
2
3
2 1
0 0 1
1 1 1

## 输出样例:

1
1

分析

首先讲解下什么是二维前缀和

但是本题的特殊之处在于给的目标是在交叉点上,而上面给的是第几个矩阵

解决方法:平移坐标系,原来在坐标轴上的目标就变成了在坐标轴内的目标,进一步就是变成了和原来一样的第几个小正方形

所以先将目标的value填充到对应的方格中,然后计算value的前缀和矩阵,最后利用计算出的前缀和矩阵,通过移动覆盖面积的小方形,以其右下角为基准遍历整个矩阵,计算覆盖面积的最大值

前缀和的灵魂就是将本来时间复杂度\(O(n)\)甚至\(O(n^2)\)的循环遍历求和变成\(O(1)\)

注意:

1 题目中一个坐标处可能有多个目标

2 如果火力覆盖面积比最大的5000还大,那就可以不用遍历直接得到答案

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.time.chrono.MinguoChronology;
import java.util.Scanner;


public class Main {
static int MAXSIZE = 5010;
static int[][] matrix = new int[MAXSIZE][MAXSIZE];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int r = scan.nextInt();
r = Math.min(r, 5001);
int max_x = r;
int max_y = r;
// 填充一小格的价值
for(int i = 0; i < n; i++) {
int x = scan.nextInt();
int y = scan.nextInt();
matrix[x + 1][y + 1] += scan.nextInt();
max_x = Math.max(x + 1, max_x);
max_y = Math.max(y + 1, max_y);
}
// 计算价值的二维前缀和
for(int i = 1; i <= max_x; i++) {
for(int j = 1; j <= max_y; j++) {
matrix[i][j] += matrix[i - 1][j] + matrix[i][j - 1] - matrix[i - 1][j - 1];
}
}
int maxValue = 0;
// 移动火力覆盖的小方形遍历整个矩阵
for(int i = r; i <= max_x; i++) {
for(int j = r; j <= max_y; j++) {
int value = matrix[i][j] - matrix[i - r][j] - matrix[i][j - r] + matrix[i - r][j - r];
if(value > maxValue) {
maxValue = value;
}
}
}
System.out.println(maxValue);
scan.close();
}
}

定义一个类

1
2
3
4
class Person(object):	#objectobject 是所有类的基类,也称为顶级类或根类。在定义类时,如果没有明确指定继承的父类,则默认继承自 object 类,可以省略
def eat(self): # self 是一个惯用的命名约定,用来表示对象自身。在类的方法定义中,self 参数指向类的实例,也就是调用该方法的对象本身。通过 self,可以在方法内部访问和操作对象的属性和方法。是 Python 中定义类方法的标准做法,不可省略
''''''
def jump(self):

类中几种常见方法

__init__方法(类似与java类的构造函数)

del()方法:删除对象时自动调用,在对一个对象引用次数为0才算彻底删除

举个例子

定义一个动物的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal(object):
#定义初始化方法 创建对象时候自动调用
def __init__(self,name):
# print('__init__方法被调用')
self.name = name

#定义普通方法
def walk(self):
print('动物会跑')

#定义一个析构方法 删除对象的时候自动调用
def __del__(self):
# print('__del__方法被调用')
print('%s对象被干掉'%(self.name))

然后实例化一个猫的对象,并且多次引用

1
2
3
cat = Animal('波斯猫')
cat2 = cat
cat3 = cat

发现创建了多个cat对象

如果只删除一个,另外两个还存在

魔法方法:Python中的一种特殊方法,它们以双下划线开头和结尾,例如 __init____str____add__ 等。这些方法在特定的情况下会被Python解释器自动调用,而不需要我们显式地调用它们。

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#定义一个车类
class Car(object):
#定义初始化方法 创建对象的时候被自动调用
def __init__(self,newColor,newWheelNum):
self.color = newColor
self.wheelNum = newWheelNum

#定义一个析构方法 删除对象的时候被自动调用
def __del__(self):
print('%s对象被删除'%(self.color))

#定义一个魔方方法
def __str__(self):
# msg = '%s-%d'%(self.color,self.wheelNum)
# return msg
return self.color

#创建一个对象laosi
laosi = Car('红色',4)
# 通过print打印对象的时候,如果类中定义__str__方法,自动调用,一般方便查看类中属性值
print(laosi)
# 后面做开发的时候,想直接返回对象中属性值

#总结:如果类的属性比较多,可以重写__str__()方法打印属性,方便阅读,无需手动调用,当使用print打印对象的时候,自动调用

定义一个魔法方法

1
2
def __str__(self):
return self.color

如果类的属性比较多,可以重写__str__()方法打印属性,方便阅读,无需手动调用,当使用print打印对象的时候,自动调用

1
2
3
def __str__(self):
msg = '%s-%d'%(self.color,self.wheelNum)
return msg

str()和repr()

_str_()用于将数值转化为人阅读的形式,调用print的时候自动调用

__repr__()用于转化为解释器读取的形式

注:在没有__str__的时候,认为str == repr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import datetime

#获取当前的时间
now = datetime.datetime.now()
print(now)
# output 2024-02-05 22:12:48.663497
print(type(now))
# output <class 'datetime.datetime'>
print(str(now)) #转换成字符串
# output: 2024-02-05 22:12:48.663497
print(type(str(now)))
# output: <class 'str'>
print(repr(now))
# output: datetime.datetime(2024, 2, 5, 22, 12, 48, 663497)
print(eval(repr(now))) #eval参数是字符串表达式 repr(now)当成整体作为参数执行 再返回repr之后的结果
# output: 2024-02-05 22:12:48.663497

总结: repr返回的是字符串,一般用来获取对象

obj == eval(repr(obj)) 这个公式是成立的

继承

定义

1
2
3
4
5
class A(object):
attribute1, attribute2
def method1(self):
def method2(self):
class B(A): # 表示B继承A

如果有两个类,一个父类,一个子类,定义了同名的方法,如果实例化子类对象调用方法的时候先从子类查找 ,再一级一级往上查找

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person(object):
#定义初始化方法
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex

#定义普通方法
def eat(self):
print('人都需要吃饭')

#定义普通方法
def speak(self):
print('我会汉语')


#定义子类Student继承父类Person
class Student(Person):
#定义初始化方法
def __init__(self,no,name,age,sex):
self.no = no
# 调用父类同名方法
# 1.父类类名.父类方法
# Person.__init__(self,name,age,sex) 直接调用父类的初始化方法,并将 self(当前实例)以及需要传递的参数传递给它。
# 2.super()
# super().__init__(name,age,sex) 使用 super() 函数获取父类的引用,并调用其初始化方法,无需手动传递 self,它会自动传递。
super(Student, self).__init__(name,age,sex)
# 调用父类 Person 的 __init__ 方法,以便在创建 Student 对象时对父类属性进行初始化。

访问限制

私有,就是按java中私有属性的来理解

__双下划线后面跟属性名

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person(object):
#定义一个初始化方法
def __init__(self,name,money):
self.__name = name
self._money = money

#定义普通方法对属性设置
def setName(self,value):
#数据过滤
if len(value) <= 4:
self.__name = value
else:
print('名称的长度不能大于4个字符')
#定义普通方法获取属性值
def getName(self):
return self.__name

#定义私有方法
def __sayHello(self):
print('我的名字是:%s,我有%s存款'%(self.__name,self._money))

#定义公有方法获取私有属性
def test(self):
self.__sayHello()

半公开:_单下划线后面跟属性名

公开:直接属性名

Abstract

1 提出利用自编码器移除GAN指纹

2 创建了一个新数据集、

Introduction

db8bd2513df8ed711a4a707eae81d12

FAR:False Acceptance Rate",即误接受率,在二元分类问题中,"False Acceptance" 意味着将一个负例(非目标类别)错误地分类为正例(目标类别)

FRR:False Rejection Rate",即误拒绝率,表示在应该被接受的情况下,系统错误地拒绝的比率。

DET Curve:在 DET Curve 上,横轴通常表示 FAR(False Acceptance Rate),纵轴表示 FRR(False Rejection Rate)。曲线上的每个点对应于系统在不同的阈值下的性能。

# Related Work

Proposed Approch

GAN指纹是什么

GAN指纹指图像中GAN's architect,就是所有与真实图像不相关的东西

如何消除

先在真实图像上训练一个卷积神经网络,然后将GAN图像传入,output的就是去除GAN指纹的图像

Experiment Setup

预处理

通过68个人脸数据点中的眼睛确定人脸位置并且最大程度裁剪掉背景保留人脸

检测器的选择

题目

输入一个长度为 n 的整数序列。

接下来再输入 m 个询问,每个询问输入一对 l,r , 。

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式

第一行包含两个整数 n 和 m 。

第二行包含 n 个整数,表示整数数列。

接下来 m 行,每行包含两个整数 l 和 r ,表示一个询问的区间范围。

输出格式

共 m 行,每行输出一个询问的结果。

数据范围

1≤l≤r≤n, 1≤n,m≤100000 −1000≤数列中元素的值≤1000

输入样例:

1
2
3
4
5
5 3
2 1 3 6 4
1 2
1 3
2 4

输出样例:

1
2
3
3
6
10

分析

\(前缀和s[i] = a[1] + a[2] + …… + a[i]\)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;

public class Main {
static int[] data = new int[100010];
static int[] prefixSum = new int[100010];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
for(int i = 1; i <= n; i++) {
data[i] = scan.nextInt();
prefixSum[i] = prefixSum[i - 1] + data[i];
}
for(int i = 0; i < m; i++) {
int left = scan.nextInt();
int right = scan.nextInt();
System.out.println(prefixSum[right] - prefixSum[left - 1]);
}
scan.close();
}
}

题目

给定一个按照升序排列的长度为 n的整数数组,以及 q 个查询。

对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。

如果数组中不存在该元素,则返回 -1 -1

阅读全文 »

题目

小明正在玩一个“翻硬币”的游戏。

桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。

比如,可能情形是:**oo***oooo

如果同时翻转左边的两个硬币,则变为:oooo***oooo

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

我们约定:把翻动相邻的两个硬币叫做一步操作。

输入格式

两行等长的字符串,分别表示初始状态和要达到的目标状态。

输出格式

一个整数,表示最小操作步数

数据范围

输入字符串的长度均不超过100。 数据保证答案一定有解。

输入样例1:

1
2
**********
o****o****

输出样例1:

1
5

输入样例2:

1
2
*o**o***o***
*o***o**o***

输出样例2:

1
1

分析

贪心:如果当前位置不同,那就要翻转当前位置和当前位置的下一位,而当前位置之前的所有位置已经都是调整到和目标一样了

代码

暴搜(超时了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import java.util.Scanner;
public class Main {
static StringBuffer stringInitial;
static String stringTarget;
static StringBuffer stringOperation = new StringBuffer();
static int stringLen;
static int LEFT = -1;
static int RIGHT = 1;
static int steps = 0;
static int minSteps = Integer.MAX_VALUE;
static void reverse(int count) {
if(stringInitial.charAt(count) == '*') {
stringInitial.setCharAt(count, 'o');
} else {
stringInitial.setCharAt(count, '*');
}
}
static void change(int count, int direction) {
reverse(count);
reverse(count + direction);
}
static boolean valid() {
if(stringInitial.toString().equals(stringTarget)) {
return true;
} else {
return false;
}
}

static void printString() {
System.out.println(stringInitial);
}
static boolean flag = false;
static void dfs(int count) {
if(count == stringLen) {
if(valid() && steps < minSteps) {
minSteps = steps;
}
return;
}
// 翻当前层
if(count == 0) { // 只能翻右边
change(count, RIGHT);
steps += 1;
dfs(count + 1);
// 复位
change(count, RIGHT);
steps--;
} else if(count == stringLen - 1) { // 只能翻左边
change(count, LEFT);
steps++;
dfs(count + 1);
// 复位
change(count, LEFT);
steps--;
} else { // 两边都可以翻
// 翻右边
change(count, RIGHT);
steps++;
dfs(count + 1);
// 复位
change(count, RIGHT);
steps--;
// 翻左边
change(count, LEFT);
steps++;
dfs(count + 1);
// 复位
change(count, LEFT);
steps--;
}
// 不翻当前层
dfs(count + 1);
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String tmpString = scan.nextLine();
stringInitial = new StringBuffer(tmpString);
stringTarget = scan.nextLine();
stringLen = stringInitial.length();
dfs(0);
System.out.println(minSteps);
scan.close();
}
}

贪心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.Scanner;
public class Main {
static StringBuffer stringOperation;
static String stringTarget;
static void change(int count) {
if(stringOperation.charAt(count) == '*') {
stringOperation.setCharAt(count, 'o');
} else {
stringOperation.setCharAt(count, '*');
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String tmpString = scan.nextLine();
stringOperation = new StringBuffer(tmpString);
stringTarget = scan.nextLine();
int steps = 0;
for(int i = 0; i < stringTarget.length(); i++) {
if(stringOperation.charAt(i) != stringTarget.charAt(i)) {
change(i);
change(i + 1);
steps++;
}
}
System.out.println(steps);
scan.close();
}
}

exercise1:写一个函数求三个数的平均值(要求分别使用默认参数和不定长参数)

1
2
3
# 使用不定长参数
def fun(*args):
return sum(args) / len(args)

exercise2:偏函数

1
2
3
4
5
6
7
8
9
10
11
12
'''
键盘录入一个数字,使用偏函数计算这个数字表示n周(一周7天)的总天数
'''
# 从functools中导包
from functools import partial
# 定义原始函数
def count(days_per_week, n):
return n * days_per_week
# 利用partial装饰原始函数,就是新建了一个函数
count_days = partial(count, 7)
days = count_days(3)
print(days)