南京某理工类高校机试题
并查集+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); }