考察知识:快速排序,map的基本操作
算法难度:XX || X 实现难度:XX || X+
分析:如果用快排的话,要用分治思想,难度稍微大一些,用map就是基本操作,难度不大
如果追求速度可以写一个快速输入函数,但是注意输入是否有负数
map版代码(含快速输入):
#include
#include
考察知识:字符串,模拟
算法难度:XX 实现难度:XXX
分析:按照题目说的来就可以了,但是要注意审题,要考虑全面,如:
#include
#include
#include
#include
char str[105];
int p1,p2,p3;
int main(){
scanf("%d%d%d",&p1,&p2,&p3);
scanf("%s",str);
for(int i=0;str[i]!='\0';i++)
if(str[i]=='-'&&i&&str[i+1]!='\0'&&str[i-1]str[i-1];j--)
for(int k=1;k<=p2;k++)
if(p1==1) putchar(tolower(j));
else if(p1==2) putchar(toupper(j));
else putchar('*');
}
}
else putchar(str[i]);
return 0;
}
考察知识:高精度,区间型动态规划
算法难度:XX 实现难度:XXX
分析:
读懂题意后我们发现我们可以把矩阵拆分成n排,每排m个元素的序列,然后针对每一排序列用动态规划:
1.定义f(curi,j)表示第cur排序列[i,j]取数的最大值
2.边界:
因为最后的答案很大,使用要用高精度
代码:
#include
#include
#include
#include
using namespace std;
struct bign{
int a[200],len;
bign(){a[0]=0,len=1;memset(a,0,sizeof(a));}
void get_v(int v){
bign(); if(!v) return; len=0;
while(v) a[len++]=v%10,v/=10;
}
friend bool operator < (bign A,bign B){
if(A.len!=B.len) return A.len=0;i--) if(A.a[i]!=B.a[i])
return A.a[i]9) C.a[i+1]++,C.a[i]-=10;
while(C.len>1&&C.a[C.len-1]==0) C.len--;
return C;
}
friend bign operator * (bign A,int x){
bign C;
C.len=A.len+20;
for(int i=0;i9) C.a[i+1]+=C.a[i]/10,C.a[i]%=10;
while(C.a[C.len-1]==0&&C.len>1) C.len--;
return C;
}
friend bign operator * (bign A,bign B){
bign C;C.len=A.len+B.len;
for(int i=0;i9) C.a[i+1]+=C.a[i]/10,C.a[i]%=10;
while(C.len&&C.a[C.len-1]==0) C.len--;
return C;
}
void out(bool Entr=true){
for(int i=len-1;i>=0;i--) putchar('0'+a[i]);
if(Entr) putchar('\n');
}
}ans,f[82][82],b[82];
int n,m,a[100][100];
void calc(int cur){
for(int i=1;i<=m;i++) f[i][i]=b[m]*a[cur][i];
for(int len=2;len<=m;len++)
for(int i=1;i<=m-len+1;i++){
int j=len+i-1;
f[i][j]=max(f[i+1][j]+b[m-j+i]*a[cur][i],f[i][j-1]+b[m-j+i]*a[cur][j]);
}
ans=ans+f[1][m];
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
b[0].get_v(1);
for(int i=1;i<=m;i++) b[i]=b[i-1]+b[i-1];//预处理2^i
for(int i=1;i<=n;i++) calc(i);
ans.out();
return 0;
}
考察知识:树的基本知识,树的直径,枚举
算法难度:XXX 实现难度:XXX+
分析:题目有点乱,定义有点多,但是这道题并不难,根据题目的定义枚举可能的端点并计算偏心距就可以了
算法:
1.先找树的一条直径
2.计算直径上的每一个点到树的分支(不包含直径)的最大距离
3.枚举直径上所有距离小于s的两点,计算这一段路径的偏心距,偏心距=max(两点到直径端点(不经过这段路径)的距离,路径上每一点到这一点所在树的分支的最大距离)
参考代码:
#include
#include
using namespace std;
const int maxn=305;
struct edge{
int to,l,next;
}e[maxn*2];
int first[maxn],np;
void add(int u,int v,int l){
e[++np]=(edge){v,l,first[u]};
first[u]=np;
}
int n,s,A,B,dis[maxn],dis2[maxn],fa[maxn];
bool vis[maxn];
void dfs(int i,int F,int dist,int& R){
if(dist>dis[R]) R=i;
dis[i]=dist,fa[i]=F;
for(int p=first[i];p;p=e[p].next){
int j=e[p].to;
if(j==F) continue;
dfs(j,i,dist+e[p].l,R);
}
}
void dfs2(int i,int dist,int rt){
vis[i]=true;
dis2[rt]=max(dis2[rt],dist);
for(int p=first[i];p;p=e[p].next){
int j=e[p].to;
if(!vis[j]) dfs2(j,dist+e[p].l,rt);
}
}
void build(){
int u,v,l;
scanf("%d%d",&n,&s);
for(int i=1;i