训练16
Posted llhsbg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了训练16相关的知识,希望对你有一定的参考价值。
3991: Electoral Rolls Revision
题意:对n对数排序,从小到大输出
#include<bits/stdc++.h> using namespace std; inline int read() { int x=0; char c=getchar(); bool flag=0; while(c<‘0‘||c>‘9‘){if(c==‘-‘)flag=1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=(x<<3)+(x<<1)+c-‘0‘;c=getchar();} return flag?-x:x; } priority_queue<int,vector<int> ,greater<int> > q; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { int x=read(); q.push(x); } } while(!q.empty()) { printf("%d ",q.top()); q.pop(); } }
//快读+优先队列
4603: Interesting Calculator
题意:模拟计算器,每个按键有一个花费,问使数x变成数y的最小花费位多少,以及按键次数
#include<bits/stdc++.h> using namespace std; int cost[10][3],vis[100005]; struct node{ int step,cost,num; friend bool operator <(const node a,const node b) { return a.cost>b.cost||(a.cost==b.cost&&a.step>b.step); } }se,ans; void bfs(int e) { priority_queue<node> q;//优先队列,先优先输出花费较小(花费相同时,步长较小)的元素 q.push(se); memset(vis,0,sizeof(vis)); while(!q.empty()) { se=q.top(); q.pop(); if(vis[se.num])continue;//已经遍历过的数字跳过 vis[se.num]=1; if(se.num==e) { printf(" %d %d ",se.cost,se.step);//搜到目标状态直接输出 return ; } for(int i=0;i<=2;i++) { for(int j=0;j<10;j++) { node temp=se; if(i==0) { temp.num=temp.num*10+j; } else if(i==1) { temp.num+=j; } else { temp.num*=j; } if(temp.num<=e) {temp.cost+=cost[j][i]; temp.step++; q.push(temp);} } }//按键模拟,元素入列 } } int main() { int s,e,t=0; while(~scanf("%d%d",&s,&e)) { se.step=0; se.num=s; se.cost=0; for(int k=0;k<3;k++) for(int i=0;i<=9;i++) { scanf("%d",&cost[i][k]); }//输入按键花费 ans.cost=0x3f3f3f3f,ans.step=0x3f3f3f3f; printf("Case %d:",++t); bfs(e); } }
//广搜+优先队列
#include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; const int maxn=100005; int cost[3][10]; int dis[maxn],num[maxn];//记录到i的最小花费及步长 int vis[maxn]; int s,e; int Case=1; void spfa() { memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int>q; int u,v,t; q.push(s); num[s]=dis[s]=0; while(!q.empty()) { u=q.front(); q.pop(); for(int i=0;i<3;i++) for(int j=0;j<10;j++) { if(i==0) v=u*10+j; else if(i==1) v=u+j; else v=u*j;//计算器按键过程模拟 if(v>e)//v>e表面后续按键过程均无法得到e break; if(dis[v]<=dis[u]+cost[i][j]) continue; dis[v]=dis[u]+cost[i][j]; num[v]=num[u]+1; if(!vis[v]) { vis[v]=1; q.push(v); } } } printf("Case %d: %d %d ",Case++,dis[e],num[e]); } int main() { while(~scanf("%d%d",&s,&e)) { for(int i=0;i<3;i++) for(int j=0;j<10;j++) scanf("%d",&cost[i][j]);//记录按键花费 spfa(); } }
//spfa
3407: Parenthesis
题意:删括号,将表达式中可以省略的括号删除
#include<bits/stdc++.h> using namespace std; string s; stack<int> st; int len; int check(int l,int r) { int cnt=0; for(int i=l;i<=r;i++) if(s[i]==‘(‘) cnt++; else if(s[i]==‘)‘) cnt--; else if(s[i]==‘+‘&&cnt==0) return 0; return 1; } int main() { while(cin>>s) { while(1) //每次处理一对括号 { int flag=0; len=s.size(); while(st.size())st.pop();//栈清空 for(int i=0;i<len;i++) { if(s[i]==‘(‘)//‘(‘下标入栈 st.push(i); else if(s[i]==‘)‘) { int x=st.top();//获得匹配的‘(’ st.pop(); if((x==0||s[x-1]==‘+‘||s[x-1]==‘(‘)&&(i==len-1||s[i+1]==‘+‘||s[i+1]==‘)‘))//符合条件 字符串删除括号 { s.erase(x,1); s.erase(i-1,1); flag=1; break; } else if(check(x+1,i-1))//上述条件不符合时,查询括号内字符串是否为加分表达式,不是则同样删除括号 { s.erase(x,1); s.erase(i-1,1); flag=1; break; } } } if(flag==0) break;//未出现括号多余,表达式符合条件,退出循环 } cout<<s<<endl; } }
//模拟
5971: Cable master
题意:给多条线,需要k条同样长度的线,问可得到线的最大长度
#include<bits/stdc++.h> using namespace std; int a[10005],sum; int n,k; bool work(int mid) { int sum=0; for(int i=1;i<=n;i++) { sum+=a[i]/mid; } return sum>=k; } int main() { while(~scanf("%d %d",&n,&k)) { int right=0,left=1; for(int i=1;i<=n;i++) { double x; scanf("%lf",&x); a[i]=x*100; right=max(right,a[i]); } int ans=0; while(left<=right) { int mid=(left+right)/2; if(work(mid)) left=mid+1,ans=max(ans,mid); else right=mid-1; } printf("%.2f ",ans*1.0/100.0); } }
//二分
4355: Red/Blue Spanning Tree
题意:给一个无向同图,边分为红蓝两色,问是否能构成最小生成树恰好有k条蓝色边(两点之间最大有一条边)
思路:进行两次最小生成树生成,一次优先红色边得到最小蓝色边数,一次优先蓝色边得到最大蓝色边数,如果k在范围内则存在恰好k条蓝色边的最小生成树
#include<bits/stdc++.h> using namespace std; struct edge { int x,y,flag; }e[1005*1005]; int cmp(edge a,edge b) { return a.flag<b.flag; } int f[1005],k1,k2; int find(int x) { return f[x]==-1?x:f[x]=find(f[x]); } void Union(edge x,int *p) { int t1=find(x.x); int t2=find(x.y); if(t1!=t2) { f[t1]=t2; if(x.flag==1)(*p)++; } } int main() { int n,m,k; while(~scanf("%d%d%d",&n,&m,&k),n||m||k) { char ch; int len=0,x,y; for(int i=1;i<=m;i++) { getchar(); ch=getchar(); scanf("%d %d",&e[i].x,&e[i].y); if(ch==‘B‘)e[i].flag=1; else e[i].flag=0; } sort(e+1,e+m+1,cmp); k1=0,k2=0; memset(f,-1,sizeof(f)); for(int i=1;i<=m;i++) { Union(e[i],&k1); } memset(f,-1,sizeof(f)); for(int i=m;i>=1;i--) { Union(e[i],&k2); } if(k>=k1&&k2>=k)printf("1 "); else printf("0 "); } }
//最小生成树
1589: Six Degrees of Cowvin Bacon
题意:一共有m部电影n头牛,每部电影有一定数量的牛一起合作,规定牛与自身的距离为0,与一起合作过的牛距离为1,与没有一起合作过但是有间接联系(与同一头牛合作过)的牛距离为2,求所有牛与其他牛的最小距离平均值
#include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; int f[305][305],p[305]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(i==j) f[i][j]=0; else f[i][j]=INF; } for(int i=1;i<=m;i++) { int t; scanf("%d",&t); for(int j=1;j<=t;j++) { scanf("%d",&p[j]); } for(int j=1;j<=t;j++) { for(int z=j+1;z<=t;z++) f[p[j]][p[z]]=f[p[z]][p[j]]=1; } } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { f[i][j]=min(f[i][j],f[i][k]+f[k][j]); } int maxn=INF; for(int i=1;i<=n;i++) { int sum=0; for(int j=1;j<=n;j++) { sum+=f[i][j]; } maxn=min(maxn,sum); } printf("%d ",maxn*100/(n-1)); }
//floyd算法
2200: An Old Stone Game
题意:给一个树,根节点为1 ,有如下规则:
1.玩家可以拥有k个石头,并放入水桶。2.玩家可以从水桶中取一块石头。3.当某一节点的所有r个子节点都放上石头时,玩家可以将r个石头取回,并放放置一个石头在该节点上.4当在根结点上有一颗石头时,玩家胜利
问最少取多少块石头可以取得胜利
#include<bits/stdc++.h> using namespace std; vector<int> to[205]; void init() { for(int i=1;i<=200;i++) to[i].clear(); } int cmp(int x,int y) { return x>y; } int dfs(int x) { if(!to[x].size())return 1; int num[205],maxn=-1; for(int i=0;i<to[x].size();i++) { num[i]=dfs(to[x][i]); } sort(num,num+to[x].size(),cmp); for(int i=0;i<to[x].size();i++) maxn=max(maxn,num[i]+i); return maxn; } int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); init(); for(int i=1;i<=n;i++) { int p,x; scanf("%d",&p); scanf("%d",&x); for(int j=1;j<=x;j++) { int num; scanf("%d",&num); to[p].push_back(num); } } cout<<dfs(1)<<endl; } }
//递归
3868: Nearby Cows
题意:有n个牧场,以及m条牧场之间的路,每个牧场都有各自的牛,问每个牧场出发,走k条路以内能到达的牧场的奶牛数量。
#include<bits/stdc++.h> using namespace std; const int Max=100005; struct edge { int to,pos; }e[Max*2]; int len,f[Max],brother[Max]; int dp[Max][21];//dp[i][j]记录i牧场走j条路的牧场数 void add_edge(int x,int y) { e[++len].to=y; e[len].pos=f[x]; f[x]=len; } int main() { int n,k; scanf("%d%d",&n,&k); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add_edge(x,y);//存边 add_edge(y,x); brother[x]++;//与x牧场连接的牧场树 brother[y]++; } for(int i=1;i<=n;i++) scanf("%d",&dp[i][0]);//i牧场自身的奶牛数量 for(int i=1;i<=k;i++) for(int j=1;j<=n;j++) { for(int z=f[j];z;z=e[z].pos) dp[j][i]+=dp[e[z].to][i-1];//dp[j][i]由相连节点的i-1状态相加 if(i>1)dp[j][i]-=(brother[j]-1)*dp[j][i-2];//去掉重复的 else dp[j][1]+=dp[j][0]; } for(int i=1;i<=n;i++) { printf("%d ",dp[i][k]); } }
//树形DP
以上是关于训练16的主要内容,如果未能解决你的问题,请参考以下文章
ubuntu16.04 yum报错:There are no enabled repos. Run “yum repolist all“ to see the repos you have.(代码片段