L2-1. 集合相似度
stl set模板,以后复习可以看一下,当模板用了,去重很有用呀

#include <cstdio> #include <set> using namespace std; set<int> s[50]; int main(){ //freopen("G:\input.in", "r", stdin); int n; scanf("%d", &n); for (int i = 0; i < n; ++i){ int num, x; for (scanf("%d", &num); num; --num){ scanf("%d", &x); s[i].insert(x); } } int k; for (scanf("%d", &k); k; --k){ int a, b; scanf("%d%d", &a, &b); int counta = s[a - 1].size(), countb = s[b - 1].size(); int cnt = 0; for (set<int>::iterator iter = s[a - 1].begin(); iter != s[a - 1].end(); ++iter){ if (s[b - 1].find(*iter) != s[b - 1].end()) cnt++; } printf("%.2lf%% ", cnt*1.0/(counta+countb-cnt)*100); } return 0; }
L2-2. 树的遍历
已知后序和中序输出层次遍历
比如test的
7 2 3 1 5 7 6 4 1 2 3 4 5 6 7
思路:后序遍历按左右中的关系遍历,中序按左中右的关系遍历,所以后序遍历的最后一个4必然是整颗树的root,中序数组中的4前面的1 2 3必然是4(root)的左子树,1 2 3当作一个树,继续推导这颗树的root,(1 2 3)在后序数组可以确定root为1,在确定(1 2 3)树的左右子树..
然后可以发现这是一个递归的过程,我的方法是递归的恢复原来的这颗树,至于层次遍历,我是用queue实现的

#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <string> #include <map> #include <set> #include <algorithm> using namespace std; const int inf = 0x3f3f3f; const int MAXN = 3e1+10; using namespace std; struct tree{ tree*l; tree*r; int d; }; int L[MAXN],M[MAXN]; map<int ,int >mp; tree* addnode(int d){ tree*nt = (tree*)malloc(sizeof(tree)); nt->d = d; nt->l = NULL; nt->r = NULL; return nt; } tree* dfs(int s,int e,int top){ if(s>e)return NULL; if(s==e){ return addnode(M[s]); } int mmax = 0,rootd; for(int i=s;i<=e;i++){ if(mmax<mp[M[i]]){ mmax = mp[M[i]]; rootd = M[i]; } } int mid; for(int i=s;i<=e;i++){ if(M[i]==rootd){ mid = i; break; } } tree*root = addnode(rootd); if(mid!=s) root->l = dfs(s,mid-1,2*top+1); if(mid!=e) root->r = dfs(mid+1,e,2*top+2); return root; } //queue实现层次遍历 void print(tree*root){ queue<tree*>Q; Q.push(root); while(!Q.empty()){ tree *tf; tf = Q.front(); Q.pop(); if(tf!=root)cout<<" "; cout<<tf->d; if(tf->l!=NULL)Q.push(tf->l); if(tf->r!=NULL)Q.push(tf->r); } cout<<endl; } void del(tree*root){ if(!root)return; del(root->l); del(root->r); free(root); } int main() { int n; while(scanf("%d",&n)!=EOF){ for(int i=0;i<n;i++){ scanf("%d",&L[i]); mp[L[i]] = i; } for(int i=0;i<n;i++){ scanf("%d",&M[i]); } tree*root = dfs(0,n-1,0); print(root); del(root); } return 0; }
L2-3. 家庭房产
裸并查集
0000~9999 节点都已经唯一确定,所以用一维数组做就好了,本来想用map<string,string>,输出方便一点,奈何gg了,不会改,输出了奇怪的东西,原来数组开小了,开了几个小时orz

#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <stack> #include <string> #include <queue> #include <map> #include <set> #include <vector> #include <algorithm> const int inf = 0x3f3f3f; const int MAXN = 1e4+10; using namespace std; struct fy{ int npcid; int faid; int maid; int k; int sid[5]; int n; int s; }; struct rel{ int minid; int tol; int n; int s; double pern; double pers; }; int father[MAXN]; int mark[MAXN]; fy a[MAXN]; rel ans[MAXN],rec[MAXN]; int n; void init(){ for(int i=0;i<MAXN;i++){ father[i] = i; mark[i] = 0; } memset(ans,0,sizeof(ans)); memset(rec,0,sizeof(rec)); } int Find(int u){ return u==father[u]?u:Find(father[u]); } void Union(int u,int v){ father[u] = Find(u); father[v] = Find(v); if(father[u]>father[v])father[father[u]] = father[v]; else father[father[v]] = father[u]; } bool cmp(const rel &a,const rel &b){ if(a.pers!=b.pers) return a.pers>b.pers; return a.minid<b.minid; } int main() { while(scanf("%d",&n)!=EOF){ init(); // cout<<Find(8888)<<endl; for(int i=0;i<n;i++){ scanf("%d%d%d",&a[i].npcid,&a[i].faid,&a[i].maid); mark[a[i].npcid] = 1; if(a[i].faid!=-1){ Union(a[i].npcid,a[i].faid); mark[a[i].faid] = 1; } if(a[i].maid!=-1){ Union(a[i].npcid,a[i].maid); mark[a[i].maid] = 1; } scanf("%d",&a[i].k); for(int j=0;j<a[i].k;j++){ scanf("%d",&a[i].sid[j]); if(a[i].sid[j]!=-1){ Union(a[i].npcid,a[i].sid[j]); mark[a[i].sid[j]] = 1; } } scanf("%d%d",&a[i].n,&a[i].s); } int fa; for(int i=0;i<n;i++){ fa = Find(a[i].npcid); ans[fa].minid = fa; ans[fa].n += a[i].n; ans[fa].s += a[i].s; } for(int i=0;i<MAXN;i++){ if(mark[i]){ fa = Find(i); ans[fa].tol ++; } } int top = 0; for(int i=0;i<MAXN;i++){ if(ans[i].tol){ rec[top] = ans[i]; rec[top].pern = rec[top].n*1.0/rec[top].tol; rec[top].pers = rec[top].s*1.0/rec[top].tol; top++; } } sort(rec,rec+top,cmp); cout<<top<<endl; for(int i=0;i<top;i++){ if(rec[i].minid<10){ cout<<"000"; }else if(rec[i].minid<100){ cout<<"00"; }else if(rec[i].minid<1000){ cout<<"0"; } printf("%d %d %.3lf %.3lf ",rec[i].minid,rec[i].tol,rec[i].pern,rec[i].pers); } } return 0; }
L2-4. 最长对称子串
注意连续子串

#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stack> #include <string> #include <queue> #include <vector> #include <map> #include <algorithm> const int inf = 0x3f3f3f; const int MAXN = 1e3+10; using namespace std; string ts1,ts2; int dp[2][MAXN]; int main() { while(getline(cin,ts1)){ // transform(ts1.begin(),ts1.end(),ts1.begin(),::tolower); int len = ts1.size(); ts2 = ts1; reverse(ts2.begin(),ts2.end()); // cout<<ts2<<endl; int mmax = 0; memset(dp,0,sizeof(dp)); for(int i=1;i<=len;i++){ for(int j=1;j<=len;j++){ if(ts1[i-1]==ts2[j-1]){ dp[i%2][j] = dp[(i-1)%2][j-1]+1; mmax = max(mmax,dp[i%2][j]); } else dp[i%2][j] = 0; } } cout<<mmax<<endl; } //cout << "Hello world!" << endl; return 0; }
L3-1. 肿瘤诊断
三维bfs

#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <stack> #include <string> #include <queue> #include <map> #include <set> #include <algorithm> const int inf = 0x3f3f3f; const int X = 1286; const int Y = 128; const int Z = 60; using namespace std; struct ip{ int x; int y; int z; }; int mov[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}}; int G[Z][X][Y]; stack<ip>S; queue<ip>Q; int x,y,z,t; int check(int nx,int ny,int nz){ if(nx<0||nx>=x||ny<0||ny>=y||nz<0||nz>=z||!G[nz][nx][ny])return 0; return 1; } int main() { while(scanf("%d%d%d%d",&x,&y,&z,&t)!=EOF){ ip tmp; for(int i=0;i<z;i++){ for(int j=0;j<x;j++){ for(int k=0;k<y;k++){ scanf("%d",&G[i][j][k]); if(G[i][j][k]){ tmp.z = i; tmp.x = j; tmp.y = k; S.push(tmp); } } } } ip tf; int cnt,sum=0; while(!S.empty()){ tf = S.top(); S.pop(); cnt = 0; if(G[tf.z][tf.x][tf.y]){ cnt = 1; G[tf.z][tf.x][tf.y] = 0; Q.push(tf); while(!Q.empty()){ tf = Q.front(); Q.pop(); int nx,ny,nz; for(int i=0;i<6;i++){ nx = tf.x+mov[i][0]; ny = tf.y+mov[i][1]; nz = tf.z+mov[i][2]; if(check(nx,ny,nz)){ tmp.x = nx; tmp.y = ny; tmp.z = nz; Q.push(tmp); cnt++; G[nz][nx][ny] = 0; } } } } //cout<<cnt<<endl; if(cnt>=t)sum+=cnt; } cout<<sum<<endl; } //cout << "Hello world!" << endl; return 0; }
L3-001. 凑零钱
背包,达到背包容量,货物越多,每个货物的val越小,同理,零钱越多,也就越散,还有注意同样数量的的货物,存在val大的货物越多,也就会有越小可能的val货物,这样才能满足字典序输出的要求
dp[i] = max(dp[i-val]+1,dp[i])

#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <stack> #include <string> #include <queue> #include <vector> #include <map> #include <algorithm> const int inf = 0x3f3f3f; const int MAXN = 1e2+10; const int MAXM = 1e4+10; using namespace std; int dp[MAXN]; int ans[MAXN]; int a[MAXM]; void print(int u){ if(u==ans[u]){ cout<<u; //cout<<"haha"<<endl; return ; } print(u-ans[u]); cout<<" "<<ans[u]; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF){ memset(dp,0,sizeof(dp)); memset(ans,0,sizeof(ans)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); for(int i=1;i<=n;i++){ for(int j=m;j>=a[i];j--){ if(dp[j-a[i]]||j==a[i]){ if(dp[j]<=dp[j-a[i]]+1){ dp[j] = dp[j-a[i]]+1; ans[j] = a[i]; } } } } /* for(int i=1;i<=m;i++){ cout<<ans[i]<<" "; } cout<<"debug"<<endl;*/ // cout<<"debug"<<endl; if(!ans[m]){ cout<<"No Solution"<<endl; continue; } print(m); cout<<endl; } //cout << "Hello world!" << endl; return 0; }
L3-003. 社交集群
还是裸并查集的题目,题目看错,wa了一次

#include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <stack> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <algorithm> const int inf = 0x3f3f3f; const int MAXN = 1e3+10; using namespace std; int father[MAXN]; int mark[MAXN]; int ans[MAXN],rec[MAXN]; int n,m; void init(){ for(int i=0;i<MAXN;i++) father[i] = i; memset(ans,0,sizeof(ans)); memset(rec,0,sizeof(rec)); memset(mark,0,sizeof(mark)); } int Find(int u){ return u==father[u]?u:Find(father[u]); } void Union(int u,int v){ father[u] = Find(u); father[v] = Find(v); father[father[u]] = father[v]; } bool cmp(const int &a,const int &b){ return a>b; } int main() { while(scanf("%d",&n)!=EOF){ init(); int v; for(int i=0;i<n;i++){ scanf("%d:",&m); for(int j=0;j<m;j++){ scanf("%d",&v); if(!mark[v]){ mark[v] = i+1; }else{ Union(i+1,mark[v]); } } } int fa; for(int i=1;i<=n;i++){ fa = Find(i); // cout<<fa<<endl; // cout<<"debug"<<endl; ans[fa]++; } int top=0; for(int i=1;i<=n;i++){ if(ans[i]) rec[top++] = ans[i]; } cout<<top<<endl; sort(rec,rec+top,cmp); cout<<rec[0]; for(int i=1;i<top;i++) cout<<" "<<rec[i]; cout<<endl; } //cout << "Hello world!" << endl; return 0; }