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;
}
来源:https://www.cnblogs.com/littlerita/p/12346776.html
