A 模拟题
思路:将数字和字母都分成独立项分别讨论,其中数字项需要注意连续数字字符需要转化成一个数字项进行判断
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
string s0,sn;
const int N=1e5+10;
int a[N],b[N];//字母0,数字1
bool solve()//false- true+
{
int i=0,j=0;
for(;i<s0.length()&&j<sn.length();i++,j++){
//cout<<i<<' '<<j<<endl;
if(a[i]==0&&b[j]==0){//两个都是字母
if(sn[j]<s0[i])return false;
if(sn[j]>s0[i])return true;
}else if(a[i]==1&&b[j]==1){//两个都是数字
int num1=0,num2=0;
while(a[i]==1){
num1=num1*10+s0[i]-'0';
i++;
}
i--;
while(b[j]==1){
num2=num2*10+sn[j]-'0';
j++;
}
j--;
//cout<<num1<<' '<<num2<<endl;
if(num1>num2)return false;
if(num1<num2)return true;
}else if(a[i]==1&&b[j]==0){
return true;
}else if(a[i]==0&&b[j]==1){
return false;
}
}
//cout<<i<<' '<<j<<endl;
if(i<s0.length())return false;
if(j<sn.length())return true;
return true;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t;
cin>>t;
cin>>s0;
for(int i=0;i<s0.length();i++){
if(isalpha(s0[i]))a[i]=0;
else a[i]=1;
}
while(t--){
cin>>sn;
memset(b,0,sizeof(b));
for(int i=0;i<sn.length();i++){
if(isalpha(sn[i]))b[i]=0;
else b[i]=1;
}
if(solve())cout<<"+"<<endl;
else cout<<"-"<<endl;
}
return 0;
}
B
题意:求最长等差数列的长度
思路:dp,首先很显然输出的最长长度最小也要是2,对数组从前往后遍历,每次取出一个公差对dp数组进行更新,取最大的长度
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5e3+10;
int a[N],dp[N][N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1);
int ans=0;
for(int i=1;i<=n;i++){
int k=i-1;
for(int j=i+1;j<=n;j++){
dp[i][j]=2;
int d=a[j]-a[i];
while(k>=1&&a[i]-a[k]<d)k--;
if(k==0||a[i]-a[k]!=d)continue;
dp[i][j]=max(dp[i][j],dp[k][i]+1);
ans=max(ans,dp[i][j]);
}
}
if(ans==0)ans=2;
cout<<ans<<endl;
return 0;
}
C 思维题
题意:求使得所有乘客都下车的最小操作数
思路:贪心,求出离出口最远的乘客所需的操作数再加上不能人挤人导致的时间延后数即所求答案
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int a[N];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int r,s,p,x,y;
cin>>r>>s>>p;
for(int i=0;i<p;i++){
cin>>x>>y;
x--,y--;//使其下标为0
if(y>=s)y++;
a[i]=abs(x-r)+abs(y-s);//每个坐标对应到出口的距离
}
sort(a,a+p,cmp);
int ans=0;
for(int i=0;i<p;i++)ans=max(ans,a[i]+i);
cout<<ans<<endl;
return 0;
}
J 暴搜题
题意:将字符串用空格分隔开使得它成为某个数的全排列
思路:因为n只到50,所以所有数要么是一位数,要么是两位数,位数没有别的可能,所以可以dfs暴搜,从字符串第一位开始先假设当前对应数字是一位数,继续往后遍历,当遍历完一遍不是全排列或者出现前导0的时候不满足条件开始回溯,继续dfs,一直到找到一组符合条件的答案就退出
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=55;
int n,path[N],tt;//path存储路径
bool vis[N];
bool flag=false;
string s;
void dfs(int u)
{
if(flag)return;
if(u>=s.size()){
for(int i=1;i<=tt;i++)cout<<path[i]<<' ';
cout<<endl;
flag=true;
return;
}
if(s[u]-'0'==0)return;
//枚举一位数情况
if(!vis[s[u]-'0']){
vis[s[u]-'0']=true;
path[++tt]=s[u]-'0';
dfs(u+1);
tt--;
vis[s[u]-'0']=false;
}
//枚举两位数情况
int num=(s[u]-'0')*10+s[u+1]-'0';
if(u+1<s.size()){
if(!vis[num]&&num<=n){
vis[num]=true;
path[++tt]=num;
dfs(u+2);
tt--;
vis[num]=false;
}
}
}
int main()
{
cin>>s;
if(s.size()<10)n=s.size();
else n=(s.size()-9)/2+9;
dfs(0);
return 0;
}