坐标移动
string str;
string sub=str.substr(0,n);//取得str的子串,从0坐标开始总计n个字符
sub=str.substr(index);//取得子串,从index下标开始的后半部分子串
stoi(string);// string向int 的转换
str.find("xxx")!=string::npos; //找到了目标子串
//pair的初始化
vec.push_back({data1,data2});
vec.push_back(make_pair(data1,data2));
vec.push_back(pair<type1,type2>(data1,data2));
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <string.h>
#include <cctype>
using namespace std;
bool bEffectiveMove(string str)
{
if(!(str[0]=='A'||str[0]=='W'||str[0]=='S'||str[0]=='D')) return false;
if(str.size()==2)
{
if(!isdigit(str[1])) return false;
}
if(str.size()==3)
{
if(!(isdigit(str[1])&&isdigit(str[2])) ) return false;
}
return true;
}
void ProcessMoves(vector<pair<string,int>>& moves)
{
int x=0;
int y=0;
for(const auto elem:moves)
{
if(elem.first=="A") x-=elem.second;
if(elem.first=="S") y-=elem.second;
if(elem.first=="D") x+=elem.second;
if(elem.first=="W") y+=elem.second;
}
cout<<x<<","<<y<<endl;
}
vector<pair<string,int>> GetMoves(string str)
{
vector<pair<string,int>> moves;
string::size_type pos=str.find(";");
string piece;
while(pos!=string::npos)
{
piece=str.substr(0,pos);
if(bEffectiveMove(piece))
{
moves.push_back(pair<string,int>(piece.substr(0,1),stoi(piece.substr(1)) ) ) ;
}
str=str.substr(pos+1);
pos=str.find(";");
}
return moves;
}
int main()
{
vector<pair<string,int>> moves;
string str;
while(getline(cin,str))
{
moves=GetMoves(str);
ProcessMoves(moves);
}
return 0;
}
字符串排序
错误的:
#include <iostream>
#include <string>
#include <string.h>
#include <cctype>
#include <map>
#include <algorithm>
using namespace std;
bool cmp(char lhs,char rhs)
{
if(islower(lhs)&&isupper(rhs)) return (lhs)<(rhs+32);
if(isupper(lhs)&&islower(rhs)) return (lhs+32)<(rhs);
return lhs<rhs;
}
string ReverseStr(string str)
{
string strRes;
map<int,char> other;
for(int i=0;i<str.size();++i)
{
if(!isalpha(str[i])) other[i]=str[i];
else strRes.push_back(str[i]);
}
sort(strRes.begin(),strRes.end(),cmp);
for(auto elem:other)
{
if(elem.first>=strRes.size()) strRes.push_back(elem.second);
else strRes.insert(strRes.begin()+elem.first,elem.second);
}
return strRes;
}
int main()
{
string str;
while(getline(cin,str))
{
cout<<ReverseStr(str)<<endl;
}
return 0;
}
正确的:
btw,为什么牛客网每次提交相同的代码执行效率都不一样呢?
#include <iostream>
#include <string>
#include <string.h>
#include <cctype>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
string ReverseStr(string str)
{
string strRes;
map<int,char> other;
for(int i=0;i<str.size();++i)
{
if(!isalpha(str[i])) other[i]=str[i];
}
vector<string> vec;
for(int i=0;i<26;++i) vec.push_back("");
for(auto elem:str)
{
if(isupper(elem)) vec[elem-'A'].push_back(elem);
if(islower(elem)) vec[elem-'a'].push_back(elem);
}
for(auto sub:vec) strRes.append(sub);
for(auto elem:other)
{
if(elem.first>=strRes.size()) strRes.push_back(elem.second);
else strRes.insert(strRes.begin()+elem.first,elem.second);
}
return strRes;
}
int main()
{
string str;
while(getline(cin,str))
{
cout<<ReverseStr(str)<<endl;
}
return 0;
}
查找兄弟单词
sort对string的操作问题
for(auto& elem : vecStrs)
{
sort(elem.begin(),elem.end());
}
//为什么不加 & 就无法实现sort的效果呢?
错误的:
不能将 word 这个单词sort之后再去比较!!!
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
vector<string> GetBroNums(vector<string> vecStrs,string word)
{
vector<string> res;
vector<string> vec=vecStrs;
for(auto& elem:vecStrs) sort(elem.begin(),elem.end());//vecStrs是排序后的
sort(word.begin(),word.end());
for(int i=0;i<vecStrs.size();++i)
{
if(vec[i]!=word && vecStrs[i]==word)
{
res.push_back(vec[i]);
}
}
sort(res.begin(),res.end());
return res;
}
int main()
{
int n=0;
scanf("%d",&n);
vector<string> words;
string word;
for(int i=0;i<n;++i)
{
cin>>word;
words.push_back(word);
}
cin>>word;
//兄弟单词的个数与位置
vector<string> res=GetBroNums(words, word);
if(res.size()!=0)
{
cout<<res.size()<<endl;
}
int k=0;
scanf("%d",&k);
if(k<res.size())
{
cout<<res[k-1]<<endl;
}
return 0;
}
正确的:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
bool isFriend(string word1, string word2)
{
if(word1==word2) return false;
sort(word1.begin(),word1.end());
sort(word2.begin(),word2.end());
return word1==word2;
}
int main()
{
int n=0;
scanf("%d",&n);
int count=0;
vector<string> words;
string word;
for(int i=0;i<n;++i)
{
cin>>word;
words.push_back(word);
}
sort(words.begin(),words.end());
//单词x
cin>>word;
int k;
scanf("%d",&k);
string kth;
for(int i=0;i<words.size();++i)
{
if(isFriend(word,words[i]))
{
++count;
if(count==k)
{
kth=words[i];
}
}
}
cout<<count<<endl;
if(k<=count)
{
cout<<kth<<endl;
}
return 0;
}
字符串加密
string 字符的大小写转换
str[i]=tupper(str[i]);
str[i]=tolwer(str[i]);
或者直接ascii码的加减,注意大写字母比对应的小写字母 小32!
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
//加密
string Encrypt(string str0)
{
string str=str0;
for(int i=0;i<str.size();++i)
{
if(isdigit(str[i]))
{
if(str[i]=='9') str[i]='0';
else str[i]+=1;
}
if(isalpha(str[i]))
{
if(isupper(str[i]))
{
if(str[i]=='Z') str[i]='a';
else{
str[i]+=1;
str[i]=tolower(str[i]);
}
}
else{
if(str[i]=='z') str[i]='A';
else{
str[i]+=1;
// str[i]+=32; 小写+32必然乱码了
str[i]=toupper(str[i]);
}
}
}
}
return str;
}
//解密
string Decrypt(string str0)
{
string str=str0;
for(int i=0;i<str.size();++i)
{
if(isdigit(str[i]))
{
if(str[i]=='0') str[i]='9';
else str[i]-=1;
}
if(isalpha(str[i]))
{
if(isupper(str[i]))
{
if(str[i]=='A') str[i]='z';
else{
str[i]-=1;
str[i]=tolower(str[i]);
}
}
else{
if(str[i]=='a') str[i]='Z';
else{
str[i]-=1;
// str[i]-=32;
str[i]=toupper(str[i]);
}
}
}
}
return str;
}
int main()
{
string str1,str2;
cin>>str1>>str2;
cout<<Encrypt(str1)<<endl;
cout<<Decrypt(str2)<<endl;
return 0;
}
落地小球运动距离与反弹高度
#include <iostream>
using namespace std;
int main()
{
int height=0;
scanf("%d",&height);
//第五次落地,设第0次弹起height高
double distance=0.0;
double dBounce=height;
double dDrop=height;
for(int i=0;i<5;++i)
{
distance+=dDrop;
dBounce=dDrop/2.0;
distance+=dBounce;
dDrop=dBounce;
}
distance-=dBounce;
printf("%f\n",distance);
printf("%f\n",dBounce);
}
称砝码(attention)
参考这位大佬的做法 称砝码_牛客博客
为什么牛客网上不能用 for ( auto & elem : set ) 呢?
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int main()
{
int iTypes;
scanf("%d",&iTypes);
vector<int> vecUnitMass;
int iMass;
for(int i=0;i<iTypes;++i)
{
scanf("%d",&iMass);
vecUnitMass.push_back(iMass);
}
int j=0;//单位质量 vecUnitMass[j]为第j+1类砝码的数量
set<int> res;
set<int> temp;
int iNum;
for(int i=0;i<iTypes;++i)
{
scanf("%d",&iNum);
for(int k=0;k<iNum;++k)
{
temp.clear();
if(res.empty()) temp={0,vecUnitMass[j]};
else
{
for(auto & elem:res)
{
temp.insert(elem+vecUnitMass[j]);
}
}
res.insert(temp.begin(),temp.end());
}
++j;
}
cout<<res.size()<<endl;
return 0;
}
从单向链表中删除指定值的节点
#include <iostream>
#include <list>
using namespace std;
void Insert(list<int>& ls,int afterElem,int elem)
{
list<int>::iterator it=ls.begin();
while(it!=ls.end())
{
if(*it==afterElem)
{
++it;
if(it==ls.end())
{
ls.push_back(elem);
}
else{
ls.insert(it, elem);
}
break;
}
++it;
}
}
int main()
{
int iNodes;
scanf("%d",&iNodes);
list<int> lst;
int after,elem;
scanf("%d",&elem);
lst.push_back(elem);//头结点
--iNodes;
while(iNodes-->0)
{
scanf("%d%d",& elem,& after);
Insert(lst, after, elem);
}
int iToDel;
scanf("%d",&iToDel);
//删除所有等于iToDel的节点
while(1)
{
list<int>::iterator it=lst.begin();
while(1)
{
if(*it==iToDel)
{
list<int>::iterator itEnd=it;++itEnd;
lst.erase(it, itEnd);
break;
}
++it;
if(it==lst.end()) break;
}
if(it==lst.end()) break;
}
for(auto elem:lst) cout<<elem<<" ";
cout<<endl;
return 0;
}
挑7
#include <iostream>
#include <string>
using namespace std;
bool WithSevenBit(int num)
{
int bit;
while(num>0)
{
bit=num%10;
if(bit==7) return true;
num/=10;
}
return false;
}
int main()
{
int n;
scanf("%d",&n);
int cnt=0;
for(int i=7;i<=n;++i)
{
if( WithSevenBit(i) || i%7==0 ) ++cnt;
}
printf("%d\n",cnt);
return 0;
}
高精度整数加法
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> Add(vector<int>& vec1, vector<int>& vec2)
{
//vec1,2都是逆序存储的 123 存的是 3 2 1
int index=0;
int k,bit;
int next=0;
vector<int> res;
while(index<vec1.size()&&index<vec2.size())
{
k=vec1[index]+vec2[index]+next;
bit=k%10;
res.push_back(bit);
next=k/10;
++index;
}
while(index<vec1.size())
{
k=vec1[index]+next;
bit=k%10;
res.push_back(bit);
next=k/10;
++index;
}
while(index<vec2.size())
{
k=vec2[index]+next;
bit=k%10;
res.push_back(bit);
next=k/10;
++index;
}
if(next!=0) res.push_back(next);
return res;
}
int main()
{
vector<int> vec1,vec2;
string str;
cin>>str;
for(int i=str.size()-1;i>=0;--i) vec1.push_back(str[i]-'0');
cin>>str;
for(int i=str.size()-1;i>=0;--i) vec2.push_back(str[i]-'0');
vector<int> res=Add(vec1,vec2);
for(int i=res.size()-1;i>=0;--i)
{
cout<<res[i];
}
cout<<endl;
}
字符串中第一个只出现一次的字符
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<char> vec;
char a;
while(1)
{
scanf("%c",&a);
if(a=='\n')
{
break;
}
else{
vec.push_back(a);
}
}
int arr[26]={0};
for(auto elem:vec)
{
++arr[elem-'a'];
}
bool bFound=false;
for(auto elem:vec)
{
if(arr[elem-'a']==1)
{
printf("%c",elem);
bFound=true;
break;
}
}
if(bFound==false) printf("%d",-1);
return 0;
}
DNA序列
#include <iostream>
#include <string>
using namespace std;
int GCRatio(string str)
{
int cnt=0;
for(int i=0;i<str.size();++i)
{
if(str[i]=='G'||str[i]=='C') ++cnt;
}
return cnt;
}
int main()
{
string str;
int n;
cin>>str>>n;
int indexMaxGC=-1;
int iGCRatio=0;
string sub;
for(int i=0;i<str.size()-n+1;++i)
{
sub=str.substr(i,n);
if(GCRatio(sub)>iGCRatio)
{
indexMaxGC=i;
iGCRatio=GCRatio(sub);
}
}
cout<<str.substr(indexMaxGC,n)<<endl;
return 0;
}
MP3光标位置
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
vector<int> disk;
int iSong;
int pos;
for(int i=1;i<=n;++i) disk.push_back(i);
iSong=1;
pos=1;//1 2 3 4
string orders;
cin>>orders;
if(n<=4)
{
for(int i=0;i<orders.size();++i)
{
if(orders[i]=='U')
{
if(pos==1) pos=n;
else --pos;
}
if(orders[i]=='D')
{
if(pos==n) pos=1;
else ++pos;
}
}
//输出
for(int k=1;k<=n;++k) cout<<k<<" ";
cout<<endl;
cout<<pos<<endl;
}
else{//pos-鼠标在屏幕的位置 与 iSong-当前选中的歌曲 不同!
for(int i=0;i<orders.size();++i)
{
if(orders[i]=='U')
{
if(pos==1)
{
if(iSong==1)
{
iSong=n;pos=4;
}
else
{
--iSong;
}
}
else
{
if(iSong==1)
{
iSong=n;
--pos;
}
else
{
--pos;
--iSong;
}
}
}
if(orders[i]=='D')
{
if(pos==4)
{
if(iSong==n)
{
iSong=1;pos=1;
}
else{
++iSong;
}
}
else{
if(iSong==n)
{
iSong=1;++pos;
}
else{
++pos;++iSong;
}
}
}
}
//输出 当前位置pos 当前歌曲 iSong
int arr[5]={0};
arr[pos]=iSong;
int now=iSong;
for(int i=pos-1;i>=1;--i)
{
--iSong;
if(iSong==0)
{
iSong=n;
}
arr[i]=iSong;
}
iSong=now;
for(int i=pos+1;i<=4;++i)
{
++iSong;
if(iSong==n+1)
{
iSong=1;
}
arr[i]=iSong;
}
for(int i=1;i<=4;++i)
{
cout<<arr[i]<<" ";
}
cout<<endl;
cout<<now<<endl;
}
return 0;
}
矩阵乘法
#include <iostream>
using namespace std;
int main()
{
int x,y,z;
cin>>x>>y>>z;
int a[100][100],b[100][100];
int elem;
for(int i=1;i<=x;++i)//x行
{
for(int j=1;j<=y;++j)//y列
{
scanf("%d",&elem);
a[i][j]=elem;
}
}
for(int i=1;i<=y;++i)//y行
{
for(int j=1;j<=z;++j)//z列
{
scanf("%d",&elem);
b[i][j]=elem;
}
}
//乘法
int res[100][100];
for(int i=1;i<=x;++i)//x行
{
for(int j=1;j<=z;++j)//z列
{
//res[i][j]为a数组 i行元素 与b数组 j列元素元素对应乘积之和
for(int k=1;k<=y;++k)
{
res[i][j]+=a[i][k]*b[k][j];
}
}
}
//输出
for(int i=1;i<=x;++i)//x行
{
for(int j=1;j<=z;++j)
{
cout<<res[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
字符串中连续最长的数字子串
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
void test(string str)
{
int longest=0;
vector<string> subs;
int start=0,end=0;
for(int i=0;i<str.size();++i)
{
if(isdigit(str[i]))
{
start=i;
end=i;
while(isdigit(str[end])) ++end;
if((end-start)>longest)
{
longest=end-start;
}
subs.push_back(str.substr(start,end-start));
i=end-1;
}
}
//最长的是longest
for(int i=0;i<subs.size();++i)
{
if(subs[i].size()==longest)
{
cout<<subs[i];
}
}
cout<<","<<longest<<endl;
}
int main()
{
string str;
while(cin>>str)
{
test(str);
}
return 0;
}
整数与IP地址的转换
要点
1. 数据范围,int 无法表示ip转化成的整数,这里用了long long,可以先考虑ip转换整数的最大值
2. copy不负责申请空间,直接就 copy 有问题
3. string 与 int 的相互转换
//C++11 引入了一些很方便的函数,比如:
to_string(...);
stoi(string);
#include <iostream>
#include <vector>
#include <math.h>
#include <string>
#include <algorithm>
using namespace std;
vector<int> DecToBin(int num)
{
vector<int> res;
int bit;
for(int i=31;i>=0;--i)
{
bit=(num>>i)&1;
res.push_back(bit);
}
return res;
}
long long BinToDec(vector<int> bits)
{
long long res=0;
int index=bits.size()-1;
int power=0;
for(;index>=0;--index)
{
res+=bits[index]*pow(2,power);
++power;
}
return res;
}
long long IpToNum(string str)
{
vector<int> binbits;
string sub;
int temp;
vector<int> bits;//
int post=0;
for(int i=0;i<str.size();++i)
{
post=i;
while(str[post]!='.' && post<str.size())
{
++post;
}
sub=str.substr(i,post-i);
temp=stoi(sub);
bits=DecToBin(temp);//32位
bits.erase(bits.begin(), bits.begin()+24);
//copy(bits.begin(),bits.end(),binbits.end()); 注意copy不负责申请空间
for(auto elem:bits) binbits.push_back(elem);
i=post;
}
return BinToDec(binbits);
}
string NumToIp(int num)
{
vector<int> temp=DecToBin(num);
vector<int> bits;
//统一处理为32 bits
if(temp.size()<32)
{
for(int i=0;i<32-temp.size();++i)
{
bits.push_back(0);
}
}
for(auto elem:temp) bits.push_back(elem);
vector<int> vec;
string res;
for(int i=0;i<bits.size();++i)
{
vec.push_back(bits[i]);
if(vec.size()==8)
{
res+=to_string(BinToDec(vec));
res+='.';
vec.clear();
}
}
//
res.pop_back();
return res;
}
int main()
{
string ip,decNum;
cin>>ip>>decNum;
long num=stol(decNum);
cout<<IpToNum(ip)<<endl;
cout<<NumToIp(num)<<endl;
return 0;
}
求解立方根(二分)
#include <iostream>
#include <iomanip>
using namespace std;
double GetCubeRoot(double num)
{
//转换为正数
double n=num;
if(num<0) n=-num;
double left=0,right=n;
if(n<1) right=1;
double mid,res;
while(left<right)
{
mid=(left+right)/2.0;
if(mid*mid*mid>n)
{
right=mid;
}
else{
left=mid;
}
//达到精度
if((right-left)<0.01)
{
// res=((int)(right*100))/100.0;
res=right;
break;
}
}
if(num<0) res=-res;
return res;
}
int main()
{
double num;
while(cin>>num)
{
cout<<setiosflags(ios::fixed)<<setprecision(1)<<GetCubeRoot(num)<<endl;
}
return 0;
}
迷宫问题(递归)
一些说明
1. 地图从1开始,上到下为x轴正向,左到右为y轴正向
2. visited为标志下一个位置是否走过了,0 代表没走过,可以尝试
#include <iostream>
#include <vector>
using namespace std;
vector<pair<int,int>> NextMove(int n, int m, int x, int y)
{
vector<pair<int,int>> moves;
//左上右下
if(y>=2) moves.push_back(pair<int,int>(x,y-1));
if(x>=2) moves.push_back(pair<int,int>(x-1,y));
if(y<=m-1) moves.push_back(pair<int,int>(x,y+1));
if(x<=n-1) moves.push_back(pair<int,int>(x+1,y));
return moves;
}
//x,y为当前位置
bool FindPath(vector<vector<int>>& map,vector<pair<int,int>>& path, vector<vector<int>>& visited,int n, int m, int x, int y)
{
if(x==n && y==m ) return true;
vector<pair<int,int>> Nexts=NextMove(n,m,x,y);
bool WrongPath=true;
for(auto elem:Nexts)
{
if( visited[elem.first][elem.second]==0
&& map[elem.first][elem.second]==0 )
{
WrongPath=false;
{
path.push_back(pair<int,int>(elem.first,elem.second));
visited[elem.first][elem.second]=1;
}
bool res=FindPath(map, path, visited, n, m, elem.first, elem.second);
if(res) return true;
//注意:别在这里加个什么else pop_back()
//将当前位置全尝试一遍再 pop_back()不迟!
}
}
path.pop_back();
return false;
}
int main()
{
int n,m;//n行m列
scanf("%d%d",&n,&m);
vector<vector<int>> map;
vector<int> vec;
vector<pair<int,int> > path;
//地图
for(int i=0;i<=n;++i)
{
vec.clear();
for(int j=0;j<=m;++j)
{
vec.push_back(0);
}
map.push_back(vec);
}
int elem;
for(int i=1;i<=n;++i)//行数
{
for(int j=1;j<=m;++j)
{
scanf("%d",&elem);
map[i][j]=elem;
}
}
//访问标志位
vec.clear();
vector<vector<int>> visited;
for(int i=0;i<=m;++i) vec.push_back(0);
for(int i=0;i<=n;++i) visited.push_back(vec);
path.push_back(pair<int,int>(1,1));
visited[1][1]=1;
bool res=FindPath(map,path,visited, n, m, 1, 1);
if(res)
{
//输出路径
for(auto elem:path)
{
cout<<"("<<elem.first-1<<","<<elem.second-1<<")"<<endl;
}
}
return 0;
}
计算字符串的编辑距离(DP)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
// dp[i][j]表示 前i,j个字符的距离
int dp[1010][1010];
string strA,strB;
cin>>strA>>strB;
int lena=strA.size(),lenb=strB.size();
int temp[3]={0};
for(int i=1;i<=lena;++i) dp[i][0]=i;
for(int i=1;i<=lenb;++i) dp[0][i]=i;
for(int i=1;i<=lena;++i)
{
for(int j=1;j<=lenb;++j)
{
//注意 strA,B从0开始
if(strA[i-1]==strB[j-1]) dp[i][j]=dp[i-1][j-1];//
else{
//第i,j个不同
temp[0]=dp[i-1][j-1];//换A
temp[1]=dp[i][j-1];//B插入A
temp[2]=dp[i-1][j];//删除A
sort(temp,temp+3);
dp[i][j]=temp[0]+1;
}
}
}
printf("%d",dp[lena][lenb]);
return 0;
}
trying to fully understand the dp transfer...
杨辉三角的变形
内存超限:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//奇数+偶数=奇数
int n;
scanf("%d",&n);
if(n==1 || n==2 )
{
printf("%d",-1);
return 0;
}
vector<vector<int>> triangle;
vector<int> vec;
//row从1开始
vec={-1};triangle.push_back(vec);
//有效数据
vec={1};triangle.push_back(vec);
vec={1,1,1};triangle.push_back(vec);
int elem;
for(int row=3;row<=n;++row)
{
vec={1,row-1};
for(int i=2;i<2*n-3;++i)
{
elem=triangle[row-1][i-2]+triangle[row-1][i-1]+triangle[row-1][i];
vec.push_back(elem);
}
vec.push_back(row-1);
vec.push_back(1);
triangle.push_back(vec);
}
//第n行
int index=1;
for(int i=0;i<2*n-1;++i)
{
if(triangle[n][i]%2==0)
{
break;
}
++index;
}
printf("%d",index);
return 0;
}
找规律:前4个必然有偶数,具体证明可见于注释,说实话,也不知道这个结论到底对不对。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//奇数+偶数=奇数
int n;
scanf("%d",&n);
if(n==1 || n==2 )
{
printf("%d",-1);
return 0;
}
int arr[5];
arr[1]=1;
arr[2]=n-1;
//arr[3]从第三行开始 1+2 1+2+3 1+2+3+4 ... 1+2+3+...+n-1
//i行[3]-(i-1)行[3] = i行[2],奇偶交替
//假设前4个都是奇数,可以利用奇数+奇数=偶数,偶数+奇数=奇数 等性质 得到 [3]的差 并非奇数偶数交替的
//所以前4个必有一个偶数
arr[3]=1;
for(int i=2;i<=n-1;++i)
{
arr[3]+=i;
}
bool Found=false;
for(int i=1;i<=3;++i)
{
if(arr[i]%2==0)
{
Found=true;
printf("%d",i);
break;
}
}
if(Found==false) printf("%d",4);
return 0;
}
放苹果(递归)
参考:递归_牛客博客
#include <iostream>
using namespace std;
//arg1 arg2 都大于等于2
int f(int iApples,int iPlates)
{
if(iApples<=1 || iPlates<=1 ) return 1;
//至少有iPlates-iApples个盘子空的,可以不考虑
if(iApples<iPlates) return f(iApples,iApples);
//假设每个盘子都放了苹果,每个盘子里拿掉一个也等效
//或者至少空一个盘子
else{
return f(iApples-iPlates,iPlates)+f(iApples,iPlates-1);
}
}
int main()
{
int iApples,iPlates;
scanf("%d%d",&iApples,&iPlates);
if(iApples<=1 || iPlates<=1)
{
printf("%d",1);
return 0;
}
int num=f(iApples,iPlates);
printf("%d",num);
return 0;
}
将真分数分解为埃及数
在网上copy的,https://www.cnblogs.com/repinkply/p/13406259.htmlhttps://www.cnblogs.com/repinkply/p/13406259.html不太懂:
#include<iostream>
#include<string>
using namespace std;
int main()
{
char ch='0';
int a = 0;
int b =0;
while (cin >> a >> ch >> b)
{
while (a != 1)
{
if (b % (a - 1) == 0)
{
cout << 1 << "/" << b / (a - 1) << "+";
a = 1;
}
else
{
int c=0;
c = b / a + 1; //新的埃及分数的分母
a = a - b % a; //通分后相减得到的分子
//因为:b=na+x,由通分可得分子为ac-b,c=n+1则分子为na+a-na-x=a-x,而x=b%a,所以分子为a-b%a
b = b * c; //通分后的分母
cout << 1 << "/" << c << "+";
if (b%a == 0)
{ //判断最新得到的是不是埃及分数
b = b / a;
a = 1;
}
}
}
cout << 1 << "/" << b << endl;
}
return 0;
}
之前写过一个大部分测试用例直接就超时了,只通过10%的用例。
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
// n/m (n<m) ->
vector<pair<int,int>> Transfer(int n,int m)
{
vector<pair<int,int>> res;
// a/b + c/d = (ad+bc)/bd 不约分
pair<int,int> num(1,2);
pair<int,int> sum;
while(1)
{
if(num.first*m<2*n)
{
sum.first=1;
sum.second=num.second;
break;
}
else{
num.second+=1;
}
}
//sum 已经有一个值了
res.push_back(num);
num.second+=1;
while(1)
{
if( m*(sum.first*num.second+sum.second*num.first) <= n*sum.second*num.second )
{
res.push_back(num);
sum.first=sum.first*num.second+sum.second*num.first;
sum.second=sum.second*num.second;
if( m*(sum.first*num.second+sum.second*num.first) == n*sum.second*num.second)
{
break;
}
}
// else ( m*(sum.first*num.second+sum.second*num.first) > n*sum.second*num.second )
else
{
num.second+=1;
}
}
return res;
}
int main()
{
int n,m;
string str;
vector<pair<int,int>> res;
while(getline(cin,str))
{
int index=str.find("/");
// cout<<"index"<<index<<endl;
// cout<<str.substr(0,index)<<" "<<str.substr(index+1)<<endl;
n=stoi(str.substr(0,index) );
m=stoi(str.substr(index+1) );
if(m%n==0)
{
cout<<1<<"/"<<(m/n)<<endl;
}
else{
res=Transfer(n, m);
for(int i=0;i<res.size();++i)
{
cout<<res[i].first<<"/"<<res[i].second;
if(i!=res.size()-1)
{
cout<<"+";
}
}
}
}
return 0;
}
火车进站 (递归)
int 向 string的转换 to_string()
这个也是改了一会才通过,可见对递归还不够熟悉啊,重点在还原!
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
bool Test(vector<string>& outs, string out, stack<int>& st, vector<int>& in,int iNow)//iNow仍未入栈的第一个元素
{
if(out.size()==in.size()-1)
{
outs.push_back(out);
return true;
}
if(st.size()==0)
{
//入栈
if(iNow<in.size())
{
st.push(in[iNow]);
++iNow;
Test(outs, out, st, in, iNow);
st.pop();
--iNow;
}
}
else{
//先出栈
int elem=st.top();
st.pop();
out+=to_string(elem);
Test(outs, out, st, in, iNow);
st.push(elem);
out.erase(out.begin()+out.size()-1, out.end());
//先压栈
if(iNow<in.size())
{
st.push(in[iNow]);
++iNow;
Test(outs, out, st, in, iNow);
--iNow;
st.pop();
}
}
return true;
}
int main()
{
int n;
scanf("%d",&n);
vector<int> in;in.push_back(-1);
int num;
for(int i=1;i<=n;++i)
{
scanf("%d",&num);
in.push_back(num);
}
vector<string> outs;
stack<int> st;
string out;
int iNow=1;
Test(outs, out, st, in, 1);
sort(outs.begin(),outs.end());
for(auto elem:outs)
{
for(auto train:elem)
{
cout<<train<<" ";
}
cout<<endl;
}
return 0;
}
配置文件恢复
1. 分割一个仅含空格的字符串函数
2. 匹配输入命令与合法命令行,不能用 str.find(input) != string::npos
必须要 str.find(input) == 0 ,表示从0 开始全部匹配。
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
vector<vector<string> > orders=
{
{"reset"},
{"reset","board"},
{"board","add"},
{"board","delete"},
{"reboot","backplane"},
{"backplane","abort"}
};
vector<string> Excution=
{
{"reset what"},
{"board fault"},
{"where to add"},
{"no board at all"},
{"impossible"},
{"install first"}
};
//空格分开
vector<string> SplitString(string str)
{
vector<string> res;
string sub;
int i=0,pre=0;
for(;i<str.size();++i)
{
while(str[i]==' ' && i<str.size() ) ++i;//找到非空格
if(i==str.size())
{
sub=str.substr(pre,i-pre);
res.push_back(sub);
break;
}
pre=i;//pre指向一段有效串的首字符
while(str[i]!=' ' && i<str.size() )++i;
sub=str.substr(pre,i-pre);
res.push_back(sub);
}
return res;
}
void ExcuteOrder(string str)
{
vector<string> words=SplitString(str);
if(words.size()==1)//只匹配一个关键字的命令行
{
if( orders[0][0].find(str)==0 )
{
cout<<"reset what"<<endl;
}
else{
cout<<"unknown command"<<endl;
}
}
else if(words.size()==2)
{
int cnt=0;
int indexOrder=0;
for(int i=0;i<orders.size();++i)
{
if(orders[i].size()==2)
{
if( orders[i][0].find(words[0]) ==0
&& orders[i][1].find(words[1]) ==0 )
{
++cnt;
indexOrder=i;
}
}
}
if(cnt==1)
{
cout<<Excution[indexOrder]<<endl;
}
else{
cout<<"unknown command"<<endl;
}
}
else{
cout<<"unknown command"<<endl;
}
}
int main()
{
string str;
while(getline(cin, str))
{
ExcuteOrder(str);
}
return 0;
}
参数解析
重点:与上一题(配置文件恢复)里的字符串分割一样的,不过是多个引号内合并的操作。
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
using namespace std;
vector<string> SplitString(string str)
{
vector<string> res;
string sub;
int i=0,pre=0;
for(;i<str.size();++i)
{
while( str[i]==' ' && i<str.size() ) ++i;//找到非空格
if(i==str.size())
{
sub=str.substr(pre,i-pre);
res.push_back(sub);
break;
}
if(str[i]=='"')//注意要去掉引号
{
pre=i;
++i;
while(str[i]!='"' && i<str.size() )++i;
++i;
sub=str.substr(pre+1,i-pre-2);
res.push_back(sub);
}
else{
pre=i;//pre指向一段有效串的首字符
while(str[i]!=' ' && i<str.size() )++i;
sub=str.substr(pre,i-pre);
res.push_back(sub);
}
}
return res;
}
int main()
{
string str;
vector<string> args;
while(getline(cin,str))
{
args=SplitString(str);
cout<<args.size()<<endl;
for(auto elem:args)
{
cout<<elem<<endl;
}
}
}
合法IP
提交数次,有一些测试用例没有考虑完全。
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <cctype>
using namespace std;
bool LegalIP(string str)
{
vector<int> nums;
int num;
string sub;
if(str.find(' ')!=string::npos)
{
return false;
}
int pre=0;
for(int i=0;i<str.size();++i)
{
pre=i;
if( !isdigit (str[pre]) ) return false;
while(str[i]!='.' && i<str.size() )
{
if(!isdigit(str[i])) return false;
++i;
}
sub=str.substr(pre,i-pre);
if( sub.size()>1 &&
stoi(sub.substr(0,1)) ==0 )
{
return false;
}
num=stoi(sub);
if(num<0 || num>255 ) return false;
nums.push_back(num);
}
if(nums.size()!=4) return false;
return true;
}
int main()
{
string str;
getline(cin, str);
bool res=LegalIP(str);
if(res) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return 0;
}
字符串通配符(DP)
来自大佬的代码,仅仅就个人的理解加了一些注释,仍没有完全理解透彻,虽然大致看懂了别人的代码,但是让我独立写一个好像也有点问题。
注意:如果将i, j 循环中间的赋值删掉就会在部分测试用例下失败,
eg
str1 = *h
str2 = h
v[i][0] = v[i-1][0]&&(s1[i-1]=='*')
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 判断字符是否符合要求
bool isOk(char c)
{
return (isalpha(c)||isalnum(c)||c=='.');
}
bool Match(string s1,string s2)
{
int m = s1.size();
int n = s2.size();
vector<vector<bool>> v(m+1,vector<bool>(n+1,false));
v[0][0] = true;
for(int i=1;i<=m;++i)
{
v[i][0] = v[i-1][0]&&(s1[i-1]=='*');//s1[i-1]即s1中第i个字符
for(int j=1;j<=n;++j)
{
if(isOk(s1[i-1]) &&
isOk(s2[j-1]) &&
tolower(s1[i-1]) == tolower(s2[j-1]) )
//匹配不分大小写
{
v[i][j]=v[i-1][j-1];
}
else if(s1[i-1] == '*')
//只要第j个字符是合法的,s1里第i个通配符*就能完成i,j的匹配
{
if( isOk(s2[j-1]) )
{
v[i][j]=v[i-1][j] || v[i][j-1];//*可以匹配0
}
}
else if(s1[i-1] == '?')//s2第j个合法,s1第i个通配符?可以通配单个字符
{
if( isOk(s2[j-1]) )
{
v[i][j] = v[i-1][j-1];
}
}
}
}
return v[m][n];
}
int main(void)
{
string s1,s2;
while(cin>>s1>>s2)
{
if(Match(s1, s2)){
cout << "true" << endl;
}else{
cout << "false" << endl;
}
}
return 0;
}
DP之路漫漫啊...
Redraiment的走法 (DP)
最长严格递增子序列(不要求连续)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
int num;
vector<int> pillars;
for(int i=0;i<n;++i)
{
scanf("%d",&num);
pillars.push_back(num);
}
int dp[210];
int res=0;
for(int i=0;i<pillars.size();++i)
{
dp[i]=1;
for(int j=0;j<i;++j)
{
if(pillars[j]<pillars[i])
{
dp[i]=max( dp[i],dp[j]+1);
}
res=max(dp[i],res);
}
}
printf("%d",res);
return 0;
}
表达式求值
调试了好一会儿,代码也比较乱啊,long way to go !
注意:负数与减号的区别,即 ' - ' 前无字符 或 前面字符为 ' ( ' 时为负数。
#include <iostream>
#include <stack>
#include <map>
#include <cctype>
using namespace std;
/*
( + - * / )
(
+
-
*
/
)
*/
map<char,int> mapOpertor;
int priorities[10][10];
//0 ()
//1 1优先级大 -1 1优先级小
int Priority(char operator1, char operator2)
{
int i=mapOpertor[operator1];
int j=mapOpertor[operator2];
if(priorities[i][j]>0) return 1;
else if(priorities[i][j]<0) return -1;
else return 0;
}
void InitPriorityMap()
{
char operators[6]={'(','+','-','*','/',')'};
for(int i=0;i<6;++i)
{
mapOpertor[ operators[i] ]=i+1;
}
for(int i=1;i<=5;++i) priorities[1][i]=-1;
priorities[1][6]=0;
priorities[2][1]=-1; priorities[2][2]=1; priorities[2][3]=1;
priorities[2][4]=-1; priorities[2][5]=-1; priorities[2][6]=1;
priorities[3][1]=-1; priorities[3][2]=1; priorities[3][3]=1;
priorities[3][4]=-1; priorities[3][5]=-1; priorities[3][6]=1;
priorities[4][1]=-1; priorities[4][2]=1; priorities[4][3]=1;
priorities[4][4]=1; priorities[4][5]=1; priorities[4][6]=1;
priorities[5][1]=-1; priorities[5][2]=1; priorities[5][3]=1;
priorities[5][4]=1; priorities[5][5]=1; priorities[5][6]=1;
priorities[6][1]=1; priorities[6][2]=1; priorities[6][3]=1;
priorities[6][4]=1; priorities[6][5]=1; priorities[6][6]=1;
}
int Calc(int lhs,int rhs,char op)
{
if(op=='+') return lhs+rhs;
else if(op=='-') return lhs-rhs;
else if(op=='*') return lhs*rhs;
else if(op=='/') return lhs/rhs;
return 0;
}
int main()
{
InitPriorityMap();
stack<char> stOperator;
stack<int> stOperand;
char opFront;
char opBack;
int lhs,rhs,res;
string str;
getline(cin, str);
for(int i=0;i<str.size();++i)
{
if(isdigit(str[i]))
{
int pre=i-1,ppre=i-2;
if(str[pre] == '-'
&& ( ppre<0 || str[ppre]=='(' )
)
{
stOperand.push(Calc(0, stoi(str.substr(i,1) ), str[pre] ));
if(stOperator.top()=='-') stOperator.pop();
continue;
}
//找到一个数字
int iStart=i;
while(isdigit(str[i]) ) ++i;
string sub=str.substr(iStart,i-iStart);
stOperand.push(stoi(sub));
--i;
}
else{
if(stOperand.size()==0
|| stOperator.size()==0
)
{
stOperator.push(str[i]);
continue;
}
opFront=stOperator.top();
opBack=str[i];
if(Priority(opFront, opBack)>0 )
{
lhs=stOperand.top();stOperand.pop();
rhs=stOperand.top();stOperand.pop();
res=Calc(rhs, lhs, opFront);
stOperator.pop();
stOperand.push(res);
--i;
}else if(Priority(opFront, opBack)==0)
{
stOperator.pop();
}
else
{
stOperator.push(str[i]);
}
}
}
while( stOperator.size()!=0 )
{
if(stOperator.top()==')'
|| stOperator.top()=='(') stOperator.pop();
opFront=stOperator.top(); stOperator.pop();
lhs=stOperand.top();stOperand.pop();
rhs=stOperand.top();stOperand.pop();
res=Calc(rhs, lhs, opFront);
stOperand.push(res);
}
res=stOperand.top();
printf("%d\n",res);
return 0;
}
四则运算
照搬表达式求值的代码,只是做了一个预处理:将表达式中的中括号与大括号改成小括号 (这个预处理似乎也是 有一点 glance at someone else's comment ,不过原本也准备这样试一下)
#include <iostream>
#include <stack>
#include <map>
#include <cctype>
using namespace std;
/*
( + - * / )
(
+
-
*
/
)
*/
map<char,int> mapOpertor;
int priorities[10][10];
//0 ()
//1 1优先级大 -1 1优先级小
int Priority(char operator1, char operator2)
{
int i=mapOpertor[operator1];
int j=mapOpertor[operator2];
if(priorities[i][j]>0) return 1;
else if(priorities[i][j]<0) return -1;
else return 0;
}
void InitPriorityMap()
{
char operators[6]={'(','+','-','*','/',')'};
for(int i=0;i<6;++i)
{
mapOpertor[ operators[i] ]=i+1;
}
for(int i=1;i<=5;++i) priorities[1][i]=-1;
priorities[1][6]=0;
priorities[2][1]=-1; priorities[2][2]=1; priorities[2][3]=1;
priorities[2][4]=-1; priorities[2][5]=-1; priorities[2][6]=1;
priorities[3][1]=-1; priorities[3][2]=1; priorities[3][3]=1;
priorities[3][4]=-1; priorities[3][5]=-1; priorities[3][6]=1;
priorities[4][1]=-1; priorities[4][2]=1; priorities[4][3]=1;
priorities[4][4]=1; priorities[4][5]=1; priorities[4][6]=1;
priorities[5][1]=-1; priorities[5][2]=1; priorities[5][3]=1;
priorities[5][4]=1; priorities[5][5]=1; priorities[5][6]=1;
priorities[6][1]=1; priorities[6][2]=1; priorities[6][3]=1;
priorities[6][4]=1; priorities[6][5]=1; priorities[6][6]=1;
}
int Calc(int lhs,int rhs,char op)
{
if(op=='+') return lhs+rhs;
else if(op=='-') return lhs-rhs;
else if(op=='*') return lhs*rhs;
else if(op=='/') return lhs/rhs;
return 0;
}
int main()
{
InitPriorityMap();
stack<char> stOperator;
stack<int> stOperand;
char opFront;
char opBack;
int lhs,rhs,res;
string str;
getline(cin, str);
for(int i=0;i<str.size();++i)
{
if(str[i]=='[') str[i]='(';
if(str[i]==']') str[i]=')';
if(str[i]=='{') str[i]='(';
if(str[i]=='}') str[i]=')';
}
for(int i=0;i<str.size();++i)
{
if(isdigit(str[i]))
{
int pre=i-1,ppre=i-2;
if(str[pre] == '-'
&& ( ppre<0 || str[ppre]=='(' )
)
{
stOperand.push(Calc(0, stoi(str.substr(i,1) ), str[pre] ));
if(stOperator.top()=='-') stOperator.pop();
continue;
}
//找到一个数字
int iStart=i;
while(isdigit(str[i]) ) ++i;
string sub=str.substr(iStart,i-iStart);
stOperand.push(stoi(sub));
--i;
}
else{
if(stOperand.size()==0
|| stOperator.size()==0
)
{
stOperator.push(str[i]);
continue;
}
opFront=stOperator.top();
opBack=str[i];
if(Priority(opFront, opBack)>0 )
{
lhs=stOperand.top();stOperand.pop();
rhs=stOperand.top();stOperand.pop();
res=Calc(rhs, lhs, opFront);
stOperator.pop();
stOperand.push(res);
--i;
}else if(Priority(opFront, opBack)==0)
{
stOperator.pop();
}
else
{
stOperator.push(str[i]);
}
}
}
while( stOperator.size()!=0 )
{
if(stOperator.top()==')'
|| stOperator.top()=='(') stOperator.pop();
opFront=stOperator.top(); stOperator.pop();
lhs=stOperand.top();stOperand.pop();
rhs=stOperand.top();stOperand.pop();
res=Calc(rhs, lhs, opFront);
stOperand.push(res);
}
res=stOperand.top();
printf("%d\n",res);
return 0;
}
24点游戏(递归)
参考B站up Akarinnnn_
的代码。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool Cal24(vector<double> nums)
{
if(nums.size()==1)
{
if (abs (nums[0]-24)<0.00001) return true;
else return false;
}
bool res=false;
vector<double> vec;
for(int i=0;i<nums.size();++i)
{
for(int j=0;j<nums.size();++j)
{
if(i==j) continue;
vec.clear();
for(int k=0;k<nums.size();++k)
{
if(k!=i && k!=j) vec.push_back(nums[k]);
}
double a=nums[i],b=nums[j];
vec.push_back(a+b);
if(Cal24(vec)) return true;
vec.pop_back();
vec.push_back(a-b);
if(Cal24(vec)) return true;
vec.pop_back();
vec.push_back(b-a);
if(Cal24(vec)) return true;
vec.pop_back();
vec.push_back(a*b);
if(Cal24(vec)) return true;
vec.pop_back();
if(b!=0)
{
vec.push_back(a/b);
if(Cal24(vec)) return true;
vec.pop_back();
}
}
}
return false;
}
int main()
{
int a,b,c,d;
vector<double> vec;
while(cin>>a>>b>>c>>d)
{
vec.clear();
vec.push_back(a*1.0);
vec.push_back(b*1.0);
vec.push_back(c*1.0);
vec.push_back(d*1.0);
bool res=Cal24(vec);
if(res) cout<<"true";
else cout<<"false";
cout<<endl;
}
return 0;
}
查找两个字符串a,b中的最大公共子串
直接暴力
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1,str2;
int iStart,iLength=-1;
cin>>str1>>str2;
if(str1.size()>str2.size())
{
string str=str2;
str2=str1;
str1=str;
}
//str1 是较小的串
for(int i=0;i<str1.size();++i)
{
//各种长度
for(int length=1;length<=str1.size()-i;++length)
{
string str=str1.substr(i,length);
if( str2.find(str) != string::npos
&& length>iLength )
{
iStart=i;
iLength=length;
}
}
}
cout<<str1.substr(iStart,iLength)<<endl;
return 0;
}
公共子串计算(动态规划)
可以用上面的暴力法,不过取iLength
或者DP:
注意,dp[i][j] 不是前 i 、j个字符组成子串的公共子串长度;而是 以i、j结尾的公共子串的长度,用另一个res 记录整个过程中的最大公共子串长度。
#include <iostream>
#include <string>
using namespace std;
int dp[155][155];
// dp[i][j] - 公共子串的长度,str1中以第i个字符结尾;str2中以第j个字符结尾
//好好理解下!
int CommonSubStr(string str1,string str2)
{
int len1=str1.size(),len2=str2.size();
//init
for(int i=1;i<=len1;++i) dp[i][0]=0;
for(int i=1;i<=len2;++i) dp[0][i]=0;
//
int res=0;
for(int i=1;i<=len1;++i)
{
for(int j=1;j<=len2;++j)
{
if(str1[i-1] == str2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
res=res>dp[i][j]?res:dp[i][j];
}
}
return res;
}
int main()
{
string str1,str2;
int iStart,iLength=0;
cin>>str1>>str2;
cout<<CommonSubStr(str1, str2)<<endl;
return 0;
}
密码截取(动态规划)
暴力法在部分案例超时
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string str;
cin>>str;
int iMax=1;
int iLen=str.size();
string half;
string otherhalf;
for(int i=0;i<str.size();++i)
{
//j表示右端下标
//如果右边剩下偶数个字符
if( (iLen-i)%2==0 )
{
for(int j=i;j<=(iLen-1+i)/2; ++j)
{
half=str.substr(i,j-i+1);
otherhalf=half;
reverse(otherhalf.begin(),otherhalf.end());
//偶数对称
if(str.find(otherhalf,j+1) == j+1)
{
if((j-i+1)*2 > iMax)
iMax=(j-i+1)*2;
}
//奇数对称
if(str.find(otherhalf,j+1) == j+2)//i与j
{
if((j-i+1)*2+1 > iMax)
iMax=(j-i+1)*2+1;
}
}
}
else{//右边奇数个字符
for(int j=i;j<=(iLen-1+i)/2-1; ++j)
{
half=str.substr(i,j-i+1);
otherhalf=half;
reverse(otherhalf.begin(),otherhalf.end());
//偶数对称
if(str.find(otherhalf,j+1) == j+1)
{
if((j-i+1)*2 > iMax)
iMax=(j-i+1)*2;
}
//奇数对称
if(str.find(otherhalf,j+1) == j+2)
{
if( (j-i+1)*2+1 > iMax)
iMax=(j-i+1)*2+1;
}
}
}
}
cout<<iMax<<endl;
return 0;
}
或者以单个字符中心扩散,遍历
或者DP
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string str;
cin>>str;
int iMax=1;
int j;//子串右侧的下标
bool dp[2520][2520]={false};
for(int len=0;len<str.size();++len)
{
for(int i=0;i<str.size();++i)
{
j=i+len;
if(j>=str.size()) break;
if (0==len) dp[i][j]=true;
else if (1==len)
{
if(str[i]==str[j]) dp[i][j]=true;
}
else{
dp[i][j]=dp[i+1][j-1] && str[i]==str[j];
}
if(dp[i][j] && len+1>iMax) iMax=len+1;
}
}
cout<<iMax<<endl;
return 0;
}
合唱队(动态规划)
原理:
合唱队左侧是可能不连续的递增序列,右侧是可能不连续的递减序列,中间位符合这样的条件:
正向以此结尾的递增序列长度L1,反向以此结尾的递减序列长度L2,在所有位中,中间位的 (L1+L2) 值最大。
注意:
1. 双向dp数组(正向、反向的最长递增子序列合并时dp数组也要reverse一下)
2. 双向合并时中间位计算了两次
3. reverse 的参数形式:左闭右开
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
vector<int> Height;
int h;
for(int i=0;i<n;++i)
{
scanf("%d",&h);
Height.push_back(h);
}
int dp1[3010],dp2[3010];
//
for(int i=0;i<n;++i)
{
dp1[i]=1;
for(int j=i-1;j>=0;--j)
{
if(Height[j] < Height[i] && dp1[i] < dp1[j]+1 ) dp1[i] = dp1[j]+1;
}
}
reverse(Height.begin(),Height.end());
for(int i=0;i<n;++i)
{
dp2[i]=1;
for(int j=i-1;j>=0;--j)
{
if(Height[j] < Height[i] && dp2[i] < dp2[j]+1 ) dp2[i]= dp2[j]+1;
}
}
reverse(dp2, dp2+n);
int iMax=-1;
for(int i=0;i<n;++i)
{
if(dp1[i]+dp2[i] > iMax) iMax=dp1[i]+dp2[i];
}
cout<<n-iMax+1<<endl;
return 0;
}
购物单(动态规划)
参考网上的答案 原帖
注意:moeny循环不能改成 for( j=1; j<=money; ++j )。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int iSatisfy=0;
int money,num;
scanf("%d%d",&money,&num);
int* itemPri=new int[num+1]();
int* itemImp=new int[num+1]();
int* attach1Pri=new int[num+1]();
int* attach1Imp=new int[num+1]();
int* attach2Pri=new int[num+1]();
int* attach2Imp=new int[num+1]();
int v,p,q;
for(int i=1;i<=num;++i)
{
scanf("%d%d%d",&v,&p,&q);
v/=10;
if(0==q)
{
itemPri[i]=v;
itemImp[i]=v*p;
}else if(0==attach1Pri[q]){
//q主件所属的第一个附件没有取值
attach1Pri[q]=v;
attach1Imp[q]=v*p;
}else{
attach2Pri[q]=v;
attach2Imp[q]=v*p;
}
}
money/=10;
int dp[32010];
for(int i=1;i<=num;++i)
{
for(int j=money;j>=1;--j)
{
if(j>=itemPri[i]) dp[j] = max( dp[j], dp[j-itemPri[i]] + itemImp[i] );
if(j>=itemPri[i]+attach1Pri[i]) dp[j] = max(dp[j], dp[ j-itemPri[i]-attach1Pri[i] ] + itemImp[i] + attach1Imp[i] );
if(j>=itemPri[i]+attach2Pri[i]) dp[j] = max(dp[j], dp[ j-itemPri[i]-attach2Pri[i] ] + itemImp[i] + attach2Imp[i] );
if(j>=itemPri[i]+attach1Pri[i]+attach2Pri[i])
dp[j] = max(dp[j], dp[ j-itemPri[i]-attach1Pri[i]-attach2Pri[i] ] + itemImp[i] + attach1Imp[i] + attach2Imp[i] );
}
}
cout<<dp[money]*10<<endl;
return 0;
}
矩阵乘法计算量估算
这都能过
#include <iostream>
#include <vector>
#include <stack>
#include <string>
using namespace std;
// p*q q*r 计算量 p*q*r
stack<pair<int,int>> res;
int sum;
int iM=-1;
void Multi(pair<int,int> A, pair<int,int> B)
{
pair<int,int> C;
C.first=A.first;
C.second=B.second;
sum+=A.first*A.second*B.second;
res.push(C);
}
void CalTime(vector<pair<int,int>>& matrixes,string str)
{
for(int i=0;i<str.size();++i)
{
if(str[i]=='(')
{
continue;
}
if(str[i]==')')
{
pair<int,int> rhs=res.top(); res.pop();
pair<int,int> lhs=res.top(); res.pop();
Multi(lhs, rhs);
}
if(str[i]>='A' && str[i]<='Z')
{
++iM;
res.push(pair<int,int> ( matrixes[iM].first,matrixes[iM].second) );
}
}
}
int main()
{
int n;
scanf("%d",&n);
vector<pair<int,int>> matrixes;
pair<int,int> elem;
for(int i=0;i<n;++i)
{
scanf("%d%d",&elem.first,&elem.second);
matrixes.push_back(elem);
}
string str;
cin>>str;
CalTime(matrixes, str);
printf("%d\n",sum);
return 0;
}