数字颠倒
#include<bits/stdc++.h>
using namespace std;
int main () {
int nums;
cin >> nums;
string str = to_string(nums);
reverse(str.begin(),str.end());
cout << str;
return 0;
}
- to_string(int n)将数值转化为字符串。返回对应的字符串。
- reverse() 功能是逆序(或反转),多用于字符串、数组、容器。头文件是#include reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数无返回值
句子逆序
最近reverse[a,b)很常用,我的思路,两次反转,第一次全局逐个字母反转,第二次一空格为分割逐个单词反转
- reverse(s.begin()+j,s.begin()+i);局部reverse()
简洁方法,按单词接受。边接收边逆序
#include<bits/stdc++.h>
using namespace std;
int main() {
string str, res;
while(cin >> str) {
str += " " +res;
res = str;
}
cout << res << endl;
return 0;
}
字符串排序
vector容器
vector<string> s
此时s[i]中不是一个char的字符,而是一个string型的单词!!
坐标移动
速度慢,思路感觉没啥大问题
#include<bits/stdc++.h>
using namespace std;
int main(){
pair<int , int> a(0,0);
string s;
cin>>s;
vector<string> str;
int j=0,i=0,len=0;//如何切片?
while(s[i]){
if(s[i]==';'){
str.push_back(s.substr(j,i-j));
j=i+1;
len++;
}
i++;
}
for(int i=0;i<len;i++){
string h=str[i];
int x;
if(h.size()==2){
if(h[1]>='0'&&h[1]<='9') x=(int)(h[1]-'0');
else continue;
}
else if(h.size()==3){
if(h[1]>='0'&&h[1]<='9'&&h[2]>='0'&&h[2]<='9')
x=(int)(h[1]-'0')*10+(int)(h[2]-'0');
else continue;
}
else{
continue;
}
if(h[0]=='A'){
a.first-=x;
}
if(h[0]=='D'){
a.first+=x;
}
if(h[0]=='W'){
a.second+=x;
}
if(h[0]=='S'){
a.second-=x;
}
}
cout<<a.first<<","<<a.second<<endl;
}
密码验证合格程序
islower(char c) 是否为小写字母
isuppper(char c) 是否为大写字母
isdigit(char c) 是否为数字
isalpha(char c) 是否为字母
isalnum(char c) 是否为字母或者数字
toupper(char c) 字母小转大
tolower(char c) 字母大转小
compare()
判断是否有长度超过3的相同子串没有思路
string target;
int isFound = 0;
for (int i = 0; i < s.size()-3; i ++){
for (int j = i + 3; j < s.size()-3; j ++){
// 如果字符串相同
if (0 == s.compare(i, 3, s, j, 3)){
isFound = 1;
break;
}
}
if (isFound) break;
}
if (isFound)
cout << Err << endl;
else
cout << Ok << endl;
}
- string中的字符串比较
- str1与str2比较:str1.compare(str2)
- tr1的子串(从索引3开始,包含4个字符)与str2进行比较
str1.compare(3,4,str2) - str1指定子串与str2的指定子串进行比较
str1.compare(3,4,str2,3,4)
H16 购物单
0-1背包问题
问题描述:有一个背包可以装物品的总重量为W,现有N个物品,每个物品中w[i],价值v[i],用背包装物品,能装的最大价值是多少?、
定义状态转移数组dp[i][j],表示前i个物品,背包重量为j的情况下能装的最大价值
例如,dp[3][4]=6,表示用前3个物品装入重量为4的背包所能获得的最大价值为6,此时并不是3个物品全部装入,而是3个物品满足装入背包的条件下的最大价值。
状态转移方程:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
dp[i-1][j]表示当前物品不放入背包,dp[i-1][j-w[i]]+v[i]表示当前物品放入背包,即当前第i个物品要么放入背包,要么不放入背包。
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if j-w[i]>=0:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
else:
dp[i][j] = dp[i-1][j]
return dp[m][n]
两种情况:
装不下当前物品,前n个最佳组合与前n-1个一样
装得下当前物品,求两者较大值:
装入——n-1价值加当前价值
不装入——前n个最佳组合与前n-1个一样
若想定义A = [[0,1,2],[3,4]。
vector<vector > A;
for(int i = 0; i < 2; ++i) A.push_back(vector());
A[0].push_back(0);
A[0].push_back(1);
A[0].push_back(2);
A[1].push_back(3);
A[1].push_back(4);
输入的第 1 行,为两个正整数N,m,用一个空格隔开:
(其中 N ( N<32000 )表示总钱数, m (m <60 )为可购买的物品的个数。)
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q
(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 ~ 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, m;
cin >> N >> m;//钱数 ,个数
// 由于价格是10的整数倍,处理一下以降低空间/时间复杂度
N /= 10;
vector<vector<int> > prices(61, vector<int>(3, 0)); // 价格
vector<vector<int> > priceMultiplyPriority(61, vector<int>(3, 0)); // 重要程度
for (int i = 1; i <= m; ++i) {
int a, b, c;
cin >> a >> b >> c;
a /= 10; b *= a;
if (c == 0) {//主件
prices[i][0] = a;
priceMultiplyPriority[i][0] = b;
} else {
if (prices[c][1] == 0) {//附件1
prices[c][1] = a;
priceMultiplyPriority[c][1] = b;
} else {//附件2
prices[c][2] = a;
priceMultiplyPriority[c][2] = b;
}
}
}
// 使用分组背包
vector<vector<int> > dp(m+1, vector<int>(N+1, 0));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= N; ++j) {
int a = prices[i][0], b = priceMultiplyPriority[i][0];//只有主件价格 重要程度
int c = prices[i][1], d = priceMultiplyPriority[i][1];
int e = prices[i][2], f = priceMultiplyPriority[i][2];
dp[i][j] = j >= a ? max(dp[i-1][j-a] + b, dp[i-1][j]) : dp[i-1][j];
dp[i][j] = j >= (a+c) ? max(dp[i-1][j-a-c] + b + d, dp[i][j]) : dp[i][j];
dp[i][j] = j >= (a+e) ? max(dp[i-1][j-a-e] + b + f, dp[i][j]) : dp[i][j];
dp[i][j] = j >= (a+c+e) ? max(dp[i-1][j-a-c-e] + b + d + f, dp[i][j]) : dp[i][j];
}
}
cout << dp[m][N] * 10 << endl;
}
识别有效IP地址
思路:
按行读取输入,根据字符‘~’ 将IP地址与子网掩码分开
查看子网掩码是否合法。
合法,则继续检查IP地址
非法,则相应统计项+1,继续下一行的读入
查看IP地址是否合法
合法,查看IP地址属于哪一类,是否是私有ip地址;相应统计项+1
非法,相应统计项+1
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main(){
vector<int> arr(7, 0); //分别对应题目的7个类别
string s;
while(getline(cin, s)){
int n = s.length();
vector<int> ips; //记录ip地址的数字
bool bad = false;
bool isnum = false;
int num = 0;
for(int i = 0; i < n; i++){ //遍历该ip字符串
if(s[i] == '.' || s[i] == '~'){ //以.或者~分割
if(isnum){
if(num > 255){
bad = true; //错误ip,数字不能超过255
break;
}
ips.push_back(num);
isnum = false;
num = 0;
}else{
arr[5]++; //错误地址
bad = true;
break;
}
}else if(s[i] >= '0' && s[i] <= '9'){
isnum = true;
num = num * 10 + s[i] - '0'; //计算数字
}else{
arr[5]++;
isnum = false; //错误地址,数字部分还有非数字
bad = true;
break;
}
}
if(isnum)
ips.push_back(num); //最后一个数字
if(ips[0] == 0 || ips[0] == 127 || bad)
continue; //忽略0或者127开头的地址,错误ip已经统计了过了,可以忽略
int mask = 4; //查看掩码的数字
while(mask < 8 && ips[mask] == 255)
mask++; //找到掩码第一个不全为1的数
if(mask == 8){ //掩码全1也是不合法
arr[5]++;
continue;
}else if(ips[mask] == 254 || ips[mask] == 252 || ips[mask] == 248 || ips[mask] == 240 || ips[mask] == 224 || ips[mask] == 191 || ips[mask] == 128)
mask++; //各类掩码含1的最后一位
while(mask < 8 && ips[mask] == 0)
mask++;
if(mask != 8){ //掩码后半部分不能有1
arr[5]++;
continue;
}
if(ips[0] >= 1 && ips[0] <= 126)
arr[0]++; //A类地址
else if(ips[0] >= 128 && ips[0] <= 191)
arr[1]++; //B类地址
else if(ips[0] >= 192 && ips[0] <= 223)
arr[2]++; //C类地址
else if(ips[0] >= 224 && ips[0] <= 239)
arr[3]++; //D类地址
else if(ips[0] >= 240 && ips[0] <= 255)
arr[4]++; //E类地址
if(ips[0] == 10)
arr[6]++; //私有地址10开头的
else if(ips[0] == 172 && (ips[1] >= 16 && ips[1] <= 31))
arr[6]++; //私有地址172.16.0.0-172.31.255.255
else if(ips[0] == 192 && ips[1] == 168)
arr[6]++; //私有地址192.168.0.0-192.168.255.255
}
for(int i = 0; i < 7; i++){ //输出
cout << arr[i];
if(i != 6)
cout << " ";
}
cout << endl;
return 0;
}
情况比较复杂的分类问题
- 接受数据,每段放入vector数组中
- 判断掩码,手算出全1情况——254,242,248…
简单错误记录
- for(auto a:b)中b为一个容器,效果是利用a遍历并获得b容器中的每一个值,但是a无法影响到b容器中的元素。
- for(auto x:deq)
#include<bits/stdc++.h>
using namespace std;
int main(){
string str;
map<string, int> info;
deque<string> deq;
while(getline(cin,str)){
str=str.substr(str.find_last_of('\\')+1);
int pos=str.find_last_of(' ');
if(pos>16){
str=str.substr(pos-16);
}
if(info.find(str)==info.end()){
deq.push_back(str);//队尾增加
}
++info[str];//数字加1
if(deq.size()>8) deq.pop_front();
}
for(auto x:deq){
cout << x << " " << info[x] << endl;
}
}