南京某理工类高校机试题
并查集+kruskal+坐标处理
1 const int MAXN=110;//最大点数
2 const int MAXM=100005;//最大边数
3 int F[MAXN];//并查集使用
4 struct Node {
5 int x;
6 int y;
7 } Point[1000];
8 struct Edge {
9 int u,v;
10 double w;
11 } edge[MAXM]; //存储边的信息,包括起点/终点/权值
12 int tol;//边数,加边前赋值为0
13 void addedge(int u,int v,double w) { //邻接矩阵的优化结构,kruskal单向路径就能做,没必要构造双向
14 edge[tol].u=u;
15 edge[tol].v=v;
16 edge[tol++].w=w;
17 }
18 bool cmp(Edge a,Edge b) {
19 //排序函数,讲边按照权值从小到大排序
20 return a.w<b.w;
21 }
22 int find(int x) {
23 if(F[x]==-1)
24 return x;
25 else
26 return
27 F[x]=find(F[x]);
28 }
29 double Kruskal(int n) { //传入点数,返回最小生成树的权值,如果不连通返回-1
30 memset(F,-1,sizeof(F));
31 sort(edge,edge+tol,cmp);
32 int cnt=0;//计算加入的边数
33 double ans=0;
34 for(int i=0; i<tol; i++) {
35 int u=edge[i].u;
36 int v=edge[i].v;
37 double w=edge[i].w;
38
39 int t1=find(u);
40 int t2=find(v);
41 if(t1!=t2) { //利用并查集改变顶点集合状态
42 ans+=w;
43 F[t1]=t2;
44 cnt++;
45 }
46 if(cnt==n-1) //n个结点,n-1条边,所以只要合并n-1次即可
47 break;
48 }
49 if(cnt<n-1)
50 return -1;//不连通
51 else
52 return ans;
53 }
54 double Dis(int x1,int y1,int x2,int y2) {
55 return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
56 }
57 int main() {
58 int i,j;
59 int m;
60 double w;
61
62 scanf("%d",&m);
63 for(i=1; i<=m; i++) {
64 scanf("%d %d",&Point[i].x,&Point[i].y);
65 }
66 for(i=1; i<=m; i++)
67 for(j=i+1; j<=m; j++) { //这样够造的就是有向图,减少了构造空间
68 w=Dis(Point[i].x,Point[i].y,Point[j].x,Point[j].y);
69 addedge(i,j,w);
70 }
71 printf("%.2f\n",Kruskal(m));
72 }
类似的有在上一篇文章中整理。
int func11(string str){
int n = str.length();
vector<vector<int> >dp(n,vector<int>(n));//初始化为0
for(int i=n-1;i>=0;i--){
dp[i][i] = 1;
for(int j = i+1;j<n;j++){
if(str[i]==str[j])
dp[i][j] = dp[i+1][j-1]+2;
else
dp[i][j] = max(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][n-1];
}
int main() {
string str;
cin>>str;
for(int i=0;i<str.length();i++){
if(str[i]>='A'&&str[i]<='Z'){
str[i]+=('a'-'A');
}
}
cout<<func11(str);
}