PTA天梯赛L2

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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/littlerita/p/12346776.html