标签:opera 路径 回溯 == typedef 处理 show ble 枚举
L2-001 紧急救援
题意:就是给你一张n<500的图;让你求最短路径,最短路条数,以及路径;
做法,先用dijkstra求最短路,然后dfs找最短路条数,以及点权的最大值;
一般dfs不就可以解决这个问题吗,像n皇后求次数,注意回溯即可;
那如何dfs确定这条路是最短路径呢?贪心思想,枚举每一个邻居,如果满足 dis[y.v]==dis[x]+y.w 说明当前邻居 通过这个点可以一直是最短路径,这样dfs下去,如果碰到d就return掉;
主要是没有想到用dfs求最短路径条数,然后注意回溯即可;
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++) #define per(i,j,k) for(int i=(int)k;i>=(int)j;i--) #define pb push_back #define pf push_front #define fi first #define se second typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef double db; const db PI=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3fLL; const int inf=0x3f3f3f3f;//0x7fffffff; const double eps=1e-9; const ll MOD=1e9+9; const int maxn=1e3+5; int n,m,s,d; int dis[maxn],val[maxn]; bool vis[maxn]; struct edge{int v,w;edge(int a,int b){v=a,w=b;}}; vector<edge>e[maxn]; struct node{ int id,dis; node(int a,int b){id=a,dis=b;} friend bool operator<(node a,node b){ return a.dis>b.dis; } }; void solve(){ rep(i,0,n)vis[i]=0,dis[i]=inf; dis[s]=0; priority_queue<node>Q; Q.push(node(s,0)); while(!Q.empty()){ node u=Q.top(); Q.pop(); if(vis[u.id])continue; vis[u.id]=1; for(int i=0;i<e[u.id].size();i++){ edge y=e[u.id][i]; if(vis[y.v])continue; if(dis[y.v]>y.w+u.dis){ dis[y.v]=y.w+u.dis; Q.push(node(y.v,dis[y.v])); } } } } int Max,cnt; vector<int>path,pre; void dfs(int x,int w){ if(x==d){ if(w>Max){ Max=w; path=pre; } cnt++; return ; } for(int i=0;i<e[x].size();i++){ edge y=e[x][i]; if(!vis[y.v]&&dis[y.v]==dis[x]+y.w){ vis[y.v]=1; pre.pb(y.v); dfs(y.v,w+val[y.v]); vis[y.v]=0; pre.pop_back(); } } } int main(){ scanf("%d %d %d %d",&n,&m,&s,&d); rep(i,0,n-1)scanf("%d",&val[i]); while(m--){ int a,b,c; scanf("%d %d %d",&a,&b,&c); e[a].pb(edge(b,c)); e[b].pb(edge(a,c)); } solve(); cnt=0,Max=-1; rep(i,0,n)vis[i]=0; dfs(s,val[s]); printf("%d %d\n",cnt,Max); int len=path.size(); printf("%d ",s); for(int i=0;i<len;i++) printf("%d%c",path[i],i==len-1?‘\n‘:‘ ‘); return 0; }
L2-002 链表去重
假链表
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++) #define per(i,j,k) for(int i=(int)k;i>=(int)j;i--) #define pb push_back #define pf push_front // #define fi first // #define se second typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef double db; const db PI=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3fLL; const int inf=0x3f3f3f3f;//0x7fffffff; const double eps=1e-9; const ll MOD=1e9+9; const int maxn=1e5+5; struct node{int to,k;}arr[maxn]; vector<int>lis1,lis2; bool vis[maxn]={0}; int main(){ int fi,n; scanf("%d %d",&fi,&n); for(int i=1;i<=n;i++){ int x,y,z; scanf("%d %d %d",&x,&y,&z); arr[x].k=y,arr[x].to=z; } for(int i=fi;i!=-1;i=arr[i].to){ int x=fabs(arr[i].k); if(vis[x])lis2.pb(i); else { lis1.pb(i); vis[x]=1; } } for(int i=0;i<lis1.size();i++){ int x=lis1[i]; if(i==lis1.size()-1)printf("%.5d %d -1\n",x,arr[x].k); else printf("%.5d %d %.5d\n",x,arr[x].k,lis1[i+1]); } for(int i=0;i<lis2.size();i++){ int x=lis2[i]; if(i==lis2.size()-1)printf("%.5d %d -1\n",x,arr[x].k); else printf("%.5d %d %.5d\n",x,arr[x].k,lis2[i+1]); } return 0; }
L2-003 月饼
水
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++) #define per(i,j,k) for(int i=(int)k;i>=(int)j;i--) #define pb push_back #define pf push_front #define fi first #define se second typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef double db; const db PI=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3fLL; const int inf=0x3f3f3f3f;//0x7fffffff; const double eps=1e-9; const ll MOD=1e9+9; const int maxn=1e3+5; struct node{double v,w,ave;}a[maxn]; bool cmp(node a,node b){return a.ave>b.ave;} int main(){ int n,d; scanf("%d %d",&n,&d); rep(i,1,n)scanf("%lf",&a[i].w); rep(i,1,n){ scanf("%lf",&a[i].v); a[i].ave=a[i].v/a[i].w; } sort(a+1,a+1+n,cmp); double ans=0; for(int i=1;i<=n;i++){ if(d>a[i].w)ans+=a[i].v,d-=a[i].w; else { ans+=a[i].ave*d; break; } } printf("%.2lf\n",ans); return 0; }
L2-004 这是二叉搜索树吗?
题意:给你个序列,问你是不是 BST 先序遍历或镜像的结果,是的话,输出后序遍历,
这题不会做,看完题解感觉这题很巧妙;
做法:一个 BST 先序遍历的第一个点,必为根节点,然后先序遍历去找左节点,然后回来,在这个过程中所有点都比根节点小;
在遍历右节点的时候,所有节点都比根节点大;
所以可以找一个分界线,使得分界线前面的元素都比根小,分界线后面的元素都比根大,那分界线前面的元素必是左子树上的点,分界线后面的元素必然是
右子树上的点,然后递归处理左子树和右子树,最终建成了一颗树,然后回溯时 符合后序遍历的特点,先左后右,再根;
回溯的时候有个问题,就是 root和tail 相等的时候,这时候会再递归一次,return掉以后,把节点记录下来;
确实很巧妙的题;
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++) #define per(i,j,k) for(int i=(int)k;i>=(int)j;i--) #define pb push_back #define pf push_front #define fi first #define se second typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef double db; const db PI=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3fLL; const int inf=0x3f3f3f3f;//0x7fffffff; const double eps=1e-9; const ll MOD=1e9+9; const int maxn=1e3+5; vector<int>post; int pre[maxn]; bool ismirror; void buildtree(int root,int tail){ int i=root+1; int j=tail; if(!ismirror){ while(i<=tail&&pre[i]<pre[root])i++; while(j>root&&pre[j]>=pre[root])j--; } else { while(i<=tail&&pre[i]>=pre[root])i++; while(j>root&&pre[j]<pre[root])j--; } if(i-j!=1)return ; buildtree(root+1,j); buildtree(i,tail); post.pb(pre[root]); } int main(){ int n; scanf("%d",&n); rep(i,1,n)scanf("%d",&pre[i]); ismirror=false; buildtree(1,n); if(post.size()!=n){ ismirror=true; buildtree(1,n); } if(post.size()!=n)printf("NO\n"); else { printf("YES\n"); for(int i=0;i<n;i++) printf("%d%c",post[i],i==n-1?‘\n‘:‘ ‘); } return 0; }
L2-005 集合相似度
今天才知道set也可以搞个数组;
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++) #define per(i,j,k) for(int i=(int)k;i>=(int)j;i--) #define pb push_back #define pf push_front #define fi first #define se second typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef double db; const db PI=acos(-1.0); const ll INF=0x3f3f3f3f3f3f3f3fLL; const int inf=0x3f3f3f3f;//0x7fffffff; const double eps=1e-9; const ll MOD=1e9+9; const int maxn=1e4+5; set<int>st[60]; int main(){ int k,n; scanf("%d",&n); rep(i,1,n){ int x,m; scanf("%d",&m); while(m--){ scanf("%d",&x); st[i].insert(x); } } scanf("%d",&k); while(k--){ int a,b; scanf("%d %d",&a,&b); int tot=st[a].size()+st[b].size(); set<int>::iterator it; int cnt=0; for(it=st[a].begin();it!=st[a].end();it++){ int x=*it; if(st[b].find(x)!=st[b].end())cnt++; } double ans=cnt*1.0/(tot-cnt); printf("%.2lf%\n",ans*100); } return 0; }
标签:opera 路径 回溯 == typedef 处理 show ble 枚举
原文地址:https://www.cnblogs.com/littlerita/p/12346776.html