洛谷U258357题解

原题:

## 题目背景

小红、小明和小张去看电影

小明今天看了流浪地球,小张今天看了西红柿首富

那小红该看哪一部电影呢?

## 题目描述

输入三行数字,每行两个数字,分别为小红、小明和小张对科幻片和喜剧片的喜爱程度

分别用余弦相似度和距离公式计算出该给小红推荐哪一部电影,分两行输出

## 输入格式

三行数字,一行两个,表示每个人对科幻片以及喜剧片的喜爱程度

## 输出格式

两行整型,表示该给小红推荐哪一部电影,分别用余弦相似度和距离公式计算

1表示流浪地球,0表示西红柿首富

## 样例 #1

### 样例输入 #1

```
4 5
10 10
9 9
```

### 样例输出 #1

```
0
0
```

## 提示

## 余弦相似度
 公式: $cos(\theta) = \frac{x_1x_2+y_1y_2}{\sqrt{x_1^2+y_1^2} \times {\sqrt{x_2^2+y_2^2}}}$
 ![余弦相似度示意图](https://www.luogu.com.cn/fe/api/problem/downloadAttachment/9x1ep0gq)
 $x_1 y_1$表示第一个坐标的x和y坐标
 
 $x_2 y_2$表示第二个坐标的x和y坐标
 
 结果越接近1,两个坐标越相近
 
## 距离公式
公式: $\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}$

同理

 $x_1 y_1$表示第一个坐标的x和y坐标
 
 $x_2 y_2$表示第二个坐标的x和y坐标
 
 结果越小,两个坐标越相近

题解:

# 公式解析

## 余弦相似度
原题公式是: $cos(\theta) = \frac{x_1x_2+y_1y_2}{\sqrt{x_1^2+y_1^2} \times {\sqrt{x_2^2+y_2^2}}}$

$x_1x_2+y_1y_2$ 用`C++`形式表示为 `x1*x2+y1*y2`

$\sqrt{x_1^2+y_1^2} \times {\sqrt{x_2^2+y_2^2}}$ 用`C++`形式表示为 `sqrt(x1 * x1 + y1 * y1) * sqrt(x2 * x2 + y2 * y2)`

所以整个代码可以用如下函数表示:

```cpp
#include<iostream>
#include<cmath>
using namespace std;

double yuxian(int x1, int y1, int x2, int y2){
    double result;
    result = (x1*x2+y1*y2) / (sqrt(x1 * x1 + y1 * y1) * sqrt(x2 * x2 + y2 * y2));
    return result;
}
```

## 距离公式

距离公式如下:

$ \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} $

用`C++`表示就是`sqrt(pow(x1-x2, 2) + pow(y1-y2, 2)`

所以完整函数如下:

```cpp
#include<iostream>
#include<cmath>
using namespace std;


double juli(int x1, int y1, int x2, int y2){
    double result;
    result = sqrt(pow(x1-x2, 2) + pow(y1-y2, 2));
    return result;
}
```

## 完整代码

题目中要求使用此类公式进行相似度比较,小红与谁的电影偏好越相近,就给小红推荐电影

所以我们可以使用以下代码比较

```cpp
int *bijiao(int x1,int y1, int x2, int y2, int x3, int y3){
    double result1, result2, result3, result4;
    result1 = yuxian(x1, y1, x2, y2);//小红与小明相似度
    result2 = juli(x1, y1, x2, y2);
    result3 = yuxian(x1, y1, x3, y3); // 小红与小张相似度
    result4 = juli(x1, y1, x3, y3);
       int *returnvalue = new int;
    if (result1 > result3){
        returnvalue[0] = 1; // 推荐流浪地球
    } else    returnvalue[0] = 0; // 推荐西红柿首富
    if (result2 < result4){
        returnvalue[1] = 1; // 推荐流浪地球
    }    else returnvalue[1] = 0; // 推荐西红柿首富
    return returnvalue;
}

```

值得注意的是,余弦相似度**越接近1越相近**,距离公式**越小越相近**

有了这么多函数,我们可以写主函数了

完整代码:

```cpp
#include<iostream>
#include<cmath>
using namespace std;

double yuxian(int x1, int y1, int x2, int y2){
    double result;
    result = (x1*x2+y1*y2) / (sqrt(x1 * x1 + y1 * y1) * sqrt(x2 * x2 + y2 * y2));
    return result;
}

double juli(int x1, int y1, int x2, int y2){
    double result;
    result = sqrt(pow(x1-x2, 2) + pow(y1-y2, 2));
    return result;
}
int *bijiao(int x1,int y1, int x2, int y2, int x3, int y3){
    double result1, result2, result3, result4;
    result1 = yuxian(x1, y1, x2, y2);//小红与小明相似度
    result2 = juli(x1, y1, x2, y2);
    result3 = yuxian(x1, y1, x3, y3); // 小红与小张相似度
    result4 = juli(x1, y1, x3, y3);
    int *returnvalue = new int;
    if (result1 > result3){
        returnvalue[0] = 1; // 推荐流浪地球
    } else  returnvalue[0] = 0; // 推荐西红柿首富
    if (result2 < result4){
        returnvalue[1] = 1; // 推荐流浪地球
    }   else returnvalue[1] = 0; // 推荐西红柿首富
    return returnvalue;
}
int main(){
    int x1, y1, x2, y2, x3, y3; 
    cin >> x1 >> y1;
    cin >> x2 >> y2;
    cin >> x3 >> y3;
    int *rv = new int;
    rv = bijiao(x1, y1, x2, y2, x3, y3); // 调用比较函数
    cout << rv[0] << endl; // 输出结果
    cout << rv[1] << endl;
    return 0;
}
```
拓展一个新的姿势,如果想让函数返回数组,则需要如`int *func(int par)`的声明,并且返回的数组必须用`int *sz = new int`声明

## 总结

这道题其实并不难,只要有数学基础,认真分析公式,就能解出来(应该不会还有人没发现,发题解的是作者吧)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值