# C++

前言

字符串操作是各种算法题中的常客,很多数据常常以字符串形式给出,其中有的需要自己转化成整数,而一些整型数据有时转换成字符串处理起来更加方便,比如判断一个整数是否是回文数,所以字符串和整数的转换是一些问题处理的基础步骤,C++ 在处理这类问题时并不像 Python 那样方便,但是也有许多方法能够实现,为了今后查找方便,整理如下。

int 转 string

通过 std::to_string() 函数转换

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

#include <iostream>

int main()
{
int num = 123;
std::cout << std::to_string(num);
return 0;
}

这种方式在 C++11 中才能使用,编译时记得加上 --std=c++11 的选项

## 通过 ostringstream 转换

#include <iostream>
#include <sstream>

int main()
{
int num = 123;
std::ostringstream ss;
ss << num;
std::cout << ss.str();
return 0;
}

这是一种通过字符流的方式将整数转换成字符串,这种方式在C++11之前也可以使用

通过 sprintf 转换

1
2
3
4
5
6
7
8
9
10
11
12

#include <stdio.h>

int main()
{
int num = 123;
char buffer[256];
sprintf(buffer, "%d", num);

printf("%s", buffer);
return 0;
}

这是一种C语言中的转换方式,sprintf 也可以换成更安全的 snprintf 函数

string 转 int

通过 istringstream 转换

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

#include <iostream>
#include <sstream>

int main()
{
std::string str = "668";
int num = 0;

std::istringstream ss(str);
ss >> num;

std::cout << num;
return 0;
}

使用 istringstream 可以从字符流中读取整数,与 ostringstream 是一种相反的操作

使用 sscanf 来转化

1
2
3
4
5
6
7
8
9
10
11
12
13

#include <iostream>
#include <stdio.h>

int main()
{
std::string str = "668";
int num = 0;

sscanf(str.c_str(), "%d", &num);
std::cout << num;
return 0;
}

注意 sscanf 函数的第一个参数类型是 const char *,string类型的参数需要转换一下

使用 atoi 转换

1
2
3
4
5
6
7
8
9
10

#include <iostream>
#include <stdlib.h>

int main()
{
std::string str = "668";
std::cout << atoi(str.c_str());
return 0;
}

atoi 函数的头文件是 stdlib.h,同样是一个C语言中的函数

使用方法stod

该方法在C++11中被支持,十分地方便,但是需要确保给定的string是否可以转化为double,不然会抛出错误。

总结 itoa 不是c语言标准函数,在跨平台的整数转字符串的代码中不要使用这个函数 atoi 是一个标准函数,需要将它和 itoa 区别开来,这一点很容易记混的 如果是在C++环境中进行转换,推荐使用 stringstream 字符流的形式和 to_string 函数

阅读全文 »

[[___C++]]

C++:string的运用和相关方法

一、删除std::string或std::wstring的最后一个字符:

s.pop_back();

  从s中移走最后一个元素。在string/wstring中相当于移走最后一个char/wchar_t。这个方法算是比较简单的了。

s.erase(s.end()-1);

  删除s的最后一个字符

s=s.substr(0,s.length()-1);

  取出s从最开始到倒数第二个字符之间的字符串,赋值给s。相当于去掉最后一个字符

阅读全文 »

# C++
[[___未完成]]

1.概念

  运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能。这个函数叫做运算符重载函数(常为类的成员函数)。
  用函数的方式实现了(+ - * / []数组 && || 逻辑 等)运算符的重载。根据需求决定重载那些运算符,用到的时候再百度案例即可。

阅读全文 »

# 未完成

01背包问题详解

01背包是一种动态规划问题。动态规划的核心就是状态转移方程,本文主要解释01背包状态转移方程的原理。

问题描述

01背包问题可描述为如下问题: 有一个容量为V的背包,还有n个物体。现在忽略物体实际几何形状,我们认为只要背包的剩余容量大于等于物体体积,那就可以装进背包里。每个物体都有两个属性,即体积w和价值v。 问:如何向背包装物体才能使背包中物体的总价值最大?

为什么不用贪心?

我在第一次做这个题目时考虑的是贪心算法。所谓贪心问题,就是每一步决策都采取最优解,按照此方案最后结果也是最优解。 为什么这个问题不能用贪心呢? 举个例子 我的背包容量为10,而且有4个物体,它们的体积和价值分别为
w1 = 8, v1 = 9 w2 = 3, v2 = 3 w3 = 4, v3 = 4 w4 = 3, v4 = 3 贪心是每一步采取最优拿法,即每一次都优先拿价值与体积比值最大的物体
c1 = v1/w1 = 1.125(最大) c2 = v2/w2 = 1 c3 = v3/w3 = 1 c4 = v4/w4 = 1 所以优先拿第一个物体,随后背包再也装不下其他物体了,则最大价值为9。 但是这个问题的最优解是取物体2,3,4装进背包,最大价值为3+4+3=10!!! 所以这个问题不可以用贪心法来处理。

原始的 01背包

01背包的状态转移方程为 `f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[j])

i代表对i件物体做决策,有两种方式—放入背包和不放入背包。 j表示当前背包剩余的容量。

转移方程的解释: 创建一个状态矩阵f,横坐标 i 是物体编号,纵坐标 j 为背包容量。 首先将 f 第0行和第0列初始化为0 (代码里面将整个f初始化为0了,其实只初始化第0行和第0列就够了)。这个表示不放物体时最大价值为0 。(物体编号从1开始) 接下来依次遍历f的每一行。如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for (int i = 1; i <= n; i++)
{
for (int j = V; j >= 0; j--)
{
if (j >= w[i])//如果背包装得下当前的物体
{
f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
}
else//如果背包装不下当前物体
{
f[i][j] = f[i - 1][j];
}
}
}

如果背包装得下当前的物体,在遍历过程中分别计算第i件物体放入和不放入背包的价值,取其中大的做为当前的最大价值。 如果背包装不下当前物体那么第i个物体只有不放入背包一种选择。

不放入背包时:第i次决策后的最大价值和第i-1次决策时候的价值是一样的(还是原来的那些物体,没多没少)。 放入背包时:第i次决策后的价值为 第i-1次决策时候的价值 加上 当前物体的价值v[j]。物体放入背包后会使背包容量变为 j ,即没放物体之前背包的容量为j - w[i]。

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
#include <iostream>
#include <vector>
using namespace std;
#define max(N1,N2) N1>N2?N1:N2
int main()
{
/*
第一行输入背包容量V和物体的个数n
接下来有n行,每行包含两个数字,分别为该物体的花费和价值
*/
vector<int> w, v;//w为花费,v为价值
vector<vector<int>> f;//f状态矩阵
int V, n;//V背包容量,n物体数
while (cin >> V >> n)
{
w.clear();
v.clear();
f.clear();
w.push_back(0);
v.push_back(0);

//输入原始数据
for (int i = 1; i <= n; i++)
{
int cur_w, cur_v;
cin >> cur_w >> cur_v;
w.push_back(cur_w);
v.push_back(cur_v);
}

//初始化状态矩阵
for (int i = 0; i <= n; i++)
{
vector<int> buff(V + 1, 0);
f.push_back(buff);
}

//动态规划过程
for (int i = 1; i <= n; i++)
{
for (int j = V; j >= 0; j--)
{
if (j >= w[i])
{
f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
}
else
{
f[i][j] = f[i - 1][j];
}
}
}

//输出答案
int ans = f[n][V];
cout << ans << endl;
}
return 0;
}
阅读全文 »

# 杂谈]] [[___键盘

今天是我初次选购机械键盘,有一说一就算是选择了茶轴,结果还是很吵……

总的来说到手的键盘我很满意,手感、做工、rgb灯效都很棒

但是就是有一个问题,那就是这个空格的手感相较于其他的按键来说,会有点过于拉跨,就是也不是说会发生晃动什么的,就是这个手感要比其他的按钮要烂一点,尤其是它的回弹,每次一按下去我都感觉是在按一个又沉又厚重的东西……

其实也不是很难得出它这个样子的原因,实际上空格键因为加上了卫星轴的设计,加上本身的重量比较大,所以说会导致这样的问题。

可能比较好的办法就是换一个弹簧?反正这件事情暂时没有解决。

接下来,我来总结一下这次购买的经验。

阅读全文 »

# 数学建模

一、题目描述

1
2
title: 国赛2023-B题
![[2023-B题]]

二、问题解决

1.前面两道问题

其实就是纯数学问题

总的来说不是特别难,只需要使用三角函数即可。 #### 定义: - 坡度 :\(\alpha\) - 波束的覆盖宽度:W - 相邻两条带间重叠率:η - 换能器开角:θ - 水深:D - 相邻测线间距:d - 海底坡度:αη=1-dW - (测线方向与海底坡面法向在水平面上投影的夹角β)

阅读全文 »

1
人性就是最复杂的决策问题

# 冰汽时代
# 游戏设计

在冰汽时代-《帝国的边界》中

在游戏 冰汽时代-《帝国的边界》中 游戏需要让玩家和 自己腐败的母城、温泉村、儿童矿井、废船 这四个其他的定居点进行贸易,或者进行影响。

1.游戏中过于浅层的决策系统

在游戏的后面,我发现整个系统根本就没有那么复杂:你跟他交换资源或者给予它帮助就可以增加互惠值,你只要向他们要求东西就会减低互惠值。

……互惠值其实就像是你能从他那里拿的资源的限额,其实根本不会影响之间的关系。

而你们之间还有一一个关系的值,则是由特殊事件决定的。比如说温泉村因为开发水泵把间歇泉搞爆发了,导致了温泉村的损失……然后你就选一个怪温泉还是怪自己。 - 选择怪自己:自己居民的不满值增加,你和温泉村的关系变好 - 选择怪泉水:自己居民的不满值会上升,你和温泉村的关系会变差。

就是这样的一个简单的决策,实际上这个选择对后面就没有别的影响了。我当时还以为这个水泵是关键决策……

说实话,这个决策的设计水平的前后关联度和其他的一系列东西,感觉都不如gal设计的复杂。

2.如果给他们赋予复杂的人性……

如果给他们赋予复杂的人性,增加你们之间的相互影响程度,游戏可以变得更加有意思。

是选择背叛欺骗最大化自己的利益,还是合作共赢?在这样艰苦的环境之中,我们无法不以最大的恶意来揣测对方的心理。

你需要花费事件了解对方,试探对方的底线…… 对方也会试探你的底线……

如果能够这样,那么游戏将会变得十分有意思……

1
2
3
总的来说,帝国的边界很有创意地加入了外交系统

但是整个外交系统构建得又过于简单了,如果能够复杂一点,那么整个游戏的可玩度将会大大提升。
0%