【天梯赛 - L2习题集】啃题(12 / 44)
生活随笔
收集整理的這篇文章主要介紹了
【天梯赛 - L2习题集】啃题(12 / 44)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
!L2-001 城市間緊急救援 - Dijkstra運用
!L2-002 鏈表去重 - 鏈表模擬
!L2-003 月餅 - 結構體+重載運算符+排序
!L2-004 這是二叉搜索樹嗎?- 建二叉樹模板題
L2-005 集合相似度 - set容器去重應用
L2-006 樹的遍歷 - 中后序遍歷構建樹+層序遍歷
!L2-007 家庭房產 - 并查集+結構體+排
!L2-008 最長對稱子串 - 字符串+暴力+雙指
getline和cin區別
L2-009 搶紅包 - 模擬+排序
L2-010 排座位
L2-011 玩轉二叉樹 - 前中序遍歷構建樹+層序遍歷
?L2-012 關于堆的判斷 - 優先隊列+哈希表
!L2-001 城市間緊急救援 - Dijkstra運用
思路:
#include <iostream> #include <algorithm> #include <cstring> using namespace std;const int N=510; int n,m,s,d; int g[N][N]; int dist[N],w[N],sumw[N],road[N],pre[N]; int prt[N],cnt=0; bool st[N];void dijkstra() {memset(dist,0x3f,sizeof dist);dist[s]=0;sumw[s]=w[s]; //救援隊數目road[s]=1; //最短路徑的條數 for(int i=0;i<n;i++){int t=-1;for(int j=0;j<n;j++)if(!st[j]&&(t==-1||dist[j]<dist[t]))t=j;st[t]=true;for(int j=0;j<n;j++){if(dist[j]>dist[t]+g[t][j]) //選最短路徑{dist[j]=dist[t]+g[t][j];road[j]=road[t]; //不理解sumw[j]=sumw[t]+w[j];pre[j]=t;}else if(dist[j]==dist[t]+g[t][j]){road[j]+=road[t]; //不理解if(sumw[j]<sumw[t]+w[j]){sumw[j]=sumw[t]+w[j];pre[j]=t;}}} }cout<<road[d]<<' '<<sumw[d]<<endl;//把經過的點倒序輸出 cout<<s;for(int i=d;i!=s;i=pre[i])prt[cnt++]=i;reverse(prt,prt+cnt);for(int i=0;i<cnt;i++)cout<<' '<<prt[i]; }int main() {cin>>n>>m>>s>>d;for(int i=0;i<n;i++) cin>>w[i];memset(g,0x3f,sizeof g);while(m--){int a,b,c;cin>>a>>b>>c;g[a][b]=g[b][a]=c;}dijkstra();return 0; }!L2-002 鏈表去重 - 鏈表模擬
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <cstdio> #include <vector> using namespace std;const int N=1e5+10; int head,n; int e[N],ne[N]; bool st[N];int main() {cin>>head>>n;while(n--){int idx,w,next;cin>>idx>>w>>next;e[idx]=w,ne[idx]=next;}vector<int>re,unre; //re存重復元素 unre存不重復元素 for(int i=head;i!=-1;i=ne[i]){int x=abs(e[i]);if(!st[x]){st[x]=true;unre.push_back(i);}else re.push_back(i);}//輸出去重的鏈表 for(int i=0;i<unre.size();i++){printf("%05d %d",unre[i],e[unre[i]]);if(i==unre.size()-1) puts(" -1");else printf(" %05d\n",unre[i+1]);} //輸出刪去的鏈表 for(int i=0;i<re.size();i++){printf("%05d %d",re[i],e[re[i]]);if(i==re.size()-1) puts(" -1");else printf(" %05d\n",re[i+1]);} return 0; }??
!L2-003 月餅 - 結構體+重載運算符+排序
思路:
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <cstdio> #include <vector> using namespace std;const int N=1010; int n; double d,res=0; struct node {double w,p;bool operator<(const node &t)const //按照單價由大到小排序{return p/w>t.p/t.w; } }a[N];int main() {cin>>n>>d;for(int i=0;i<n;i++) cin>>a[i].w;for(int i=0;i<n;i++) cin>>a[i].p;sort(a,a+n);for(int i=0;i<n&&d>0;i++){if(a[i].w<=d){d-=a[i].w;res+=a[i].p;}else{res+=a[i].p/a[i].w*d;break;}//這個辦法很妙↓/*double r=min(d,a[i].w);d-=r;res+=a[i].p/a[i].w*r;*/}printf("%.2f\n",res);return 0; }!L2-004 這是二叉搜索樹嗎?- 建二叉樹模板題
思路:
#include <iostream> #include <malloc.h> using namespace std;const int N=1010; int n,a[N]; int p1[N],p2[N]; int cnt1=0,cnt2=0; bool flag;typedef struct node {int data;node *l,*r; }node,*tree;tree create1(tree T,int x) {if(!T) {T=(tree)malloc(sizeof(node));T->l=nullptr,T->r=nullptr;T->data=x;}else{if(T->data>x) T->l=create1(T->l,x);else if(T->data<=x) T->r=create1(T->r,x);}return T; }tree create2(tree T,int x) {if(!T) {T=(tree)malloc(sizeof(node));T->l=nullptr,T->r=nullptr;T->data=x;}else{if(T->data<=x) T->l=create2(T->l,x);else if(T->data>x) T->r=create2(T->r,x);}return T; }void pre1(tree T) {if(!T) return;p1[cnt1++]=T->data;pre1(T->l);pre1(T->r); } void pre2(tree T) {if(!T) return;p2[cnt2++]=T->data;pre2(T->l);pre2(T->r); } void post(tree T) {if(!T) return;post(T->l);post(T->r);if(flag) cout<<' ';flag=true;cout<<T->data; }int main() {cin>>n;for(int i=0;i<n;i++) cin>>a[i];//創建二叉搜索樹 tree T1=nullptr;for(int i=0;i<n;i++) T1=create1(T1,a[i]);//創建鏡像二叉搜索樹tree T2=nullptr;for(int i=0;i<n;i++) T2=create2(T2,a[i]);//分非鏡像和鏡像進行前序遍歷 和原序列進行比較 pre1(T1),pre2(T2);bool f1=false,f2=false;for(int i=0;i<n;i++) if(p1[i]!=a[i]) f1=true;for(int i=0;i<n;i++) if(p2[i]!=a[i]) f2=true;if(f1&&f2) cout<<"NO";else if(!f1&&f2) puts("YES"),post(T1);else if(f1&&!f2) puts("YES"),post(T2);else if(!f1&&!f2) puts("YES"),post(T1);return 0; }L2-005 集合相似度 - set容器去重應用
#include <iostream> #include <set> using namespace std;const int N=1e4+10; int n,m,k;int main() {set<int>s[N];cin>>n;for(int i=1;i<=n;i++){cin>>m;while(m--){int x;cin>>x;s[i].insert(x);}}cin>>k;while(k--){int a,b,cnt=0;cin>>a>>b;for(auto x:s[a]) if(s[b].count(x)) cnt++;printf("%.2f%%\n",cnt*1.0/(s[a].size()+s[b].size()-cnt)*100);}return 0; }L2-006 樹的遍歷 - 中后序遍歷構建樹+層序遍歷
思路: 這題思路跟L2-011 玩轉二叉樹一模一樣啊 就是板子題
- 通過中后序構建樹
- 層序遍歷
!L2-007 家庭房產 - 并查集+結構體+排
#include <bits/stdc++.h> using namespace std;const int N=1e5+10; int n; int f[N]; map<int,bool>st;struct peo {int id;double cnt,area; }p[N];struct family {int anc=-1,num;double cnt,area,avg_cnt,avg_area; }fam[N];int find(int x) {if(x!=f[x]) f[x]=find(f[x]);return f[x]; }void unite(int a,int b) {int x=find(a);int y=find(b);if(x!=y) f[x]=y; }bool cmp(family a,family b) //家庭信息首先按人均面積降序輸出,若有并列,則按成員編號的升序輸出。 {if(a.avg_area!=b.avg_area)return a.avg_area>b.avg_area;else return a.anc<b.anc; }int main() {for(int i=0;i<N;i++) f[i]=i;cin>>n;for(int i=0;i<n;i++){int id,fa,ma;cin>>id>>fa>>ma;st[id]=true;if(fa!=-1) st[fa]=true,unite(id,fa);if(ma!=-1) st[ma]=true,unite(id,ma);int k;cin>>k;while(k--){int x;cin>>x;unite(x,id);st[x]=true;}int cnt,area;cin>>cnt>>area;p[id].cnt=cnt,p[id].area=area;}for(auto x:st){fam[find(x.first)].cnt+=p[x.first].cnt;fam[find(x.first)].area+=p[x.first].area;if(fam[find(x.first)].anc==-1) fam[find(x.first)].anc=x.first;fam[find(x.first)].num++;}for(int i=0;i<N;i++){if(!st[i])continue;fam[find(i)].avg_cnt=fam[find(i)].cnt/fam[find(i)].num;fam[find(i)].avg_area=fam[find(i)].area/fam[find(i)].num;}int sum=0;for(int i=0;i<N;i++) if(fam[i].num) sum++;cout<<sum<<endl;sort(fam,fam+N,cmp);for(int i=0;i<sum;i++)printf("%04d %d %.3f %.3f\n",fam[i].anc,fam[i].num,fam[i].avg_cnt,fam[i].avg_area);return 0; }!L2-008 最長對稱子串 - 字符串+暴力+雙指
getline和cin區別
getline——按行讀取, 一次讀取多個字符,直到讀滿N個(不包括空白符)為止。
形式:getline(字符指針,字符個數N,結束符);
cin——遇到結束符(包括空白符)會終止,只讀取空白符之前的部分。
#include <bits/stdc++.h> using namespace std;const int N=1e5+10;int main() {int res=0;string s;getline(cin,s); //不能用cin cin遇到空格就截止for(int i=0;i<s.size();i++)for(int j=s.size()-1;j>=i;j--){int l=i,r=j;while(l<=r&&s[l++]==s[r--])if(l>r) res=max(res,j-i+1);}cout<<res<<endl;return 0; } #include <bits/stdc++.h> using namespace std; string s; int main() {getline(cin,s);for(int len=s.size();len>0;len--) //找最大長度 倒序找for(int l=0;l+len-1<s.size();l++){bool f=false;int i=l,j=l+len-1;while(i<j){if(s[i]!=s[j]){f=true;break;}i++,j--;}if(!f){cout<<len<<endl;return 0;}} }L2-009 搶紅包 - 模擬+排序
思路:
#include <bits/stdc++.h> using namespace std;const int N=1e4+10;struct node {int id;double qiang_w,fa_w,res;int qiang_count; }a[N];bool cmp(node a,node b) {if(a.res!=b.res) return a.res>b.res;else if(a.qiang_count!=b.qiang_count) return a.qiang_count>b.qiang_count;else return a.id<b.id; }int main() {int n;cin>>n;for(int i=1;i<=n;i++) a[i].id=i;for(int i=1;i<=n;i++){int k;cin>>k;for(int j=1;j<=k;j++){int id,w;cin>>id>>w;a[id].qiang_w+=w;a[id].qiang_count++;a[i].fa_w+=w;}}for(int i=1;i<=n;i++) a[i].res=a[i].qiang_w-a[i].fa_w;sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++) printf("%d %.2f\n",a[i].id,a[i].res*1.0/100);return 0; }L2-010 排座位
思路:
#include <bits/stdc++.h> using namespace std; const int N=110; int g[N][N]; int n,m,k;bool check(int a,int b) {for(int i=1;i<=n;i++)if(g[a][i]==1&&g[b][i])return true;return false; } int main() {cin>>n>>m>>k;while(m--){int a,b,r;cin>>a>>b>>r;g[a][b]=g[b][a]=r;}while(k--){int a,b;cin>>a>>b;if(g[a][b]==1) puts("No problem");else if(g[a][b]==0) puts("OK");else if(g[a][b]==-1&&check(a,b)) puts("OK but...");else puts("No way");}return 0; }L2-011 玩轉二叉樹 - 前中序遍歷構建樹+層序遍歷
思路: 和L2-006 樹的遍歷一模一樣
- 先通過中序遍歷和前序遍歷確定出樹? 因為題目要求左右子樹對調 所以遞歸構建的時候反一下就可以了
- 然后用隊列進行層序遍歷 根節點入隊 然后根節點的左右結點入隊 每次取隊頭輸出然后扔掉
?
?L2-012 關于堆的判斷 - 優先隊列+哈希表
大頂堆:每個結點的值都大于或等于其左右孩子結點的值;
小頂堆:每個結點的值都小于或等于其左右孩子結點的值。
?思路:
- 用優先隊列PriorityQueue來實現小頂堆
- 把小頂堆轉化為數組 并更改數組下標從1開始 這樣idx/2就是父節點
- 用map存 < 結點值,下標 >
- 逐步實現四個查詢步驟即可 詳見代碼
?
總結
以上是生活随笔為你收集整理的【天梯赛 - L2习题集】啃题(12 / 44)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我糟糕的2019年:虽流年不利,但我心仍
- 下一篇: 我总结了70篇论文的方法,帮你透彻理解神