目录
L2-007 家庭房产 (25 分)(并查集+STL的应用)
L2-012 关于堆的判断 (25 分)(最小堆的建立+自下而上)
L2-022 重排链表 (25 分)(结构体运用+有一个小坑)
L2-002 链表去重 (25 分)
【分析】结构体数组,下标存该结点地址;2个vector,分别存已访问过的和未访问过的键值;输出的时候nxt输的是下一个元素的adr
和甲级的这道题一样 1097 Deduplication on a Linked List (25 分)(链表模拟)
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
struct node{
int adr;
int val;
int nxt;
}a[maxn];
int vis[maxn];
int main()
{
int adr,n;scanf("%d%d",&adr,&n);
for(int i=0;i<n;++i)
{
int adr,val,nxt;
scanf("%d%d%d",&adr,&val,&nxt);
a[adr].val=val;a[adr].nxt=nxt;a[adr].adr=adr;
}
memset(vis,0,sizeof(vis));
vector<node>v1,v2;
for(int i=adr;;i=a[i].nxt)
{
if(i==-1)break;
// cout<<"i="<<i<<","<<a[i].val<<"--\n";
if(!vis[abs(a[i].val)])v1.push_back(a[i]);
else v2.push_back(a[i]);
vis[abs(a[i].val)]=1;
}
int l1=v1.size(),l2=v2.size();
for(int i=0;i<l1;++i)
(i==l1-1)?printf("%05d %d -1\n",v1[i].adr,v1[i].val):printf("%05d %d %05d\n",v1[i].adr,v1[i].val,v1[i+1].adr);
for(int i=0;i<l2;++i)
(i==l2-1)?printf("%05d %d -1\n",v2[i].adr,v2[i].val):printf("%05d %d %05d\n",v2[i].adr,v2[i].val,v2[i+1].adr);
}
L2-003 月饼 (25 分)(排序+贪心+细节注意)
【题意】求最大收益
【分析】把收益与库存的比值+下标存入然后排序;注意库存量和售价不是整型,题上只说了是正数,但没有说是整数。所以!!如果没有注意到这一点,测试点2是过不了的.... 就会只有23分了
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
double a[maxn],b[maxn];
vector<pair<double,int> >v;
bool cmp(pair<double,int>a,pair<double,int>b)
{
return a.first<b.first;
}
int main()
{
int n,d;scanf("%d%d",&n,&d);
for(int i=0;i<n;++i)scanf("%lf",&a[i]);
for(int i=0;i<n;++i)scanf("%lf",&b[i]);
for(int i=0;i<n;++i)v.push_back(make_pair(1.0*b[i]/a[i],i));
sort(v.begin(),v.end(),cmp);
// for(int i=0;i<v.size();++i)cout<<v[i].first<<","<<v[i].second<<endl;
double sum=0;
int f=1;
for(int i=v.size()-1;i>=0;--i)
{
if(d<=0)break;
int id=v[i].second;
if(a[id]<=d)sum+=b[id],d-=a[id];
else sum+=v[i].first*d,d=0;
}
printf("%.2lf\n",sum);//如果需求大于全部加起来的库存,是要输出的
}
L2-005 集合相似度 (25 分)(set的应用)
【题意】求两个集合的都有的不相同的整数个数和一共有的的比值
【分析】二维的set存一下;(类似于vector<int>v[maxn],之前没用过,没想到可以用耶xixi开心)
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=60;
set<int>s[maxn];
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;++i)
{
int t;scanf("%d",&t);
while(t--)
{
int x;scanf("%d",&x);
s[i].insert(x);
}
}
int k;scanf("%d",&k);
while(k--)
{
int a,b;scanf("%d%d",&a,&b);
int l1=s[a].size(),l2=s[b].size();
set<int>::iterator it;
int sum=0;
for(it=s[a].begin();it!=s[a].end();++it)
if(s[b].count(*(it)))sum++;
int x=l1+l2-sum;
printf("%.2lf%\n",sum*1.0/x*100);
}
}
L2-007 家庭房产 (25 分)(并查集+STL的应用)
【分析】与 1114 Family Property (25 分)(并查集) 同;这次写得有点麻烦了,但是一遍就过还是很开心嘛~
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
int id,people=0;
double avg_num=0;
double avg_areas=0;
}a[maxn];
bool cmp(node x,node y){return x.avg_areas!=y.avg_areas?x.avg_areas>y.avg_areas:x.id<y.id;}
int pre[maxn],vis[maxn];
set<int>s;
vector<node>v;
int n;
int finds(int x){return pre[x]==x?x:pre[x]=finds(pre[x]);}
void join(int x,int y)
{
int fx=finds(x);
int fy=finds(y);
if(fx<fy)pre[fy]=fx;
else pre[fx]=fy;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<maxn;++i)pre[i]=i;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;++i)
{
int id,fa,ma,k;
scanf("%d%d%d%d",&id,&fa,&ma,&k);
vis[id]=1;
if(fa!=-1)vis[fa]=1,join(id,fa);
if(ma!=-1)vis[ma]=1,join(id,ma);
for(int i=0;i<k;++i)
{
int x;scanf("%d",&x);
join(id,x);
vis[x]=1;
}
double sets,areas;
scanf("%lf%lf",&sets,&areas);
a[id].avg_num=sets;
a[id].avg_areas=areas;
}
int f=0;
for(int i=0;i<maxn;++i)
{
if(vis[i])
{
int f=finds(i);
a[f].people++;
s.insert(f);
if(f==i)continue;
a[f].avg_num+=a[i].avg_num;
a[f].avg_areas+=a[i].avg_areas;
// cout<<"f="<<f<<endl;
}
}
int l=s.size();printf("%d\n",l);
set<int>::iterator it;
for(it=s.begin();it!=s.end();++it)
{
int x=*it;
node n;n.id=x;
n.avg_num=1.0*a[x].avg_num/a[x].people;
n.avg_areas=1.0*a[x].avg_areas/a[x].people;
n.people=a[x].people;
v.push_back(n);
}
sort(v.begin(),v.end(),cmp);
for(int i=0;i<l;++i)
{
int y=v[i].people;
printf("%04d %d %.3lf %.3lf\n",v[i].id,y,v[i].avg_num,v[i].avg_areas);
}
}
L2-008 最长对称子串 (25 分)(字符串处理)
【分析】遍历i,比较s[i-j]和s[i+j],不断维护最大值;注意奇偶数的不同
【代码】
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;getline(cin,s);
int len=s.length();
int maxx=0;
for(int i=0;i<len;++i)
{
for(int j=0;j<=i && i+j<len;++j)
{
if(s[i-j]==s[i+j+1])//cout<<i<<","<<j<<endl,
maxx=max(j+j+2,maxx);
else break;
}
}
for(int i=0;i<len;++i)
{
for(int j=0;j<=i && i+j<len;++j)
{
if(s[i-j]==s[i+j])//cout<<i<<","<<j<<endl,
maxx=max(j+j+1,maxx);
else break;
}
}
printf("%d\n",maxx);
}
L2-010 排座位 (25 分)(并查集)
【题意】分座位,有敌对关系的人不能坐在一起;朋友的朋友是朋友,敌人没有这个关系;
【分析】
- 因为朋友的朋友是朋友,但是敌对关系不满足。所以,把有直接朋友关系的人join一起
- 查询时,判断两点是否处于同一个连通块,然后根据例子画图,推算每种情况对应的两点之间的关系
- 然后~ 就好啦!
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int e[maxn][maxn];
int pre[maxn];
int n,m,k;
int finds(int x){return x==pre[x]?x:pre[x]=finds(pre[x]);}
void join(int x,int y)
{
int fx=finds(x);
int fy=finds(y);
if(fx!=fy)
pre[fx]=fy;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
memset(e,0,sizeof(e));
for(int i=0;i<=n;++i)pre[i]=i;
for(int i=0;i<m;++i)
{
int a1,a2,r;
scanf("%d%d%d",&a1,&a2,&r);
if(r==1)join(a1,a2);
e[a1][a2]=e[a2][a1]=r;
}
while(k--)
{
int x,y;scanf("%d%d",&x,&y);
int fx=finds(x),fy=finds(y);
int f;
if(fx!=fy)
{
if(e[x][y]==0)f=1;
else if(e[x][y]==-1)f=3;
}
else
{
if(e[x][y]==-1)f=2;
else f=0;
}
if(f==0)puts("No problem");
else if(f==1)puts("OK");
else if(f==2)puts("OK but...");
else if(f==3)puts("No way");
}
}
L2-012 关于堆的判断 (25 分)(最小堆的建立+自下而上)
【分析】
由给定的序列建最小堆,但是题上说的是顺序插入一个初始为空的小顶堆
所以,是边读入数据边建立堆更新堆;建堆有两种方式,并且建立出的堆是不同的...
然后就是根据输入的字符串进行相关的判断;
这里,sscanf()是c语言中的函数,这里使用的时候要转换成char*【s.c_str()】
在判断是否是兄弟结点的时候(注意这里的兄弟结点是具有同一个父节点,而不是深度相同!!!只要判断在数组中的index即可【因为是从0开始的,所以要(index-1)/2】)
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
const int inf=0x3f3f3f3f;
int a[maxn];
int n,m,cnt;
void MinHeap(int i)
{
if(i==0)return;
while(i>0)
{
if(a[i]<a[(i-1)/2])
{
swap(a[i],a[(i-1)/2]);
i=(i-1)/2;
}
else break;
}
}
int finds(int x)
{
for(int i=0;i<n;++i)
if(a[i]==x)return i;
return -1;
}
int main()
{
scanf("%d%d",&n,&m);
cnt=0;
memset(a,inf,sizeof(a));
for(int i=0;i<n;++i)
{
scanf("%d",&a[i]);
MinHeap(i);
}
getchar();
while(m--)
{
string s;getline(cin,s);
if(s.find("root")!=string::npos)
{
int x;sscanf(s.c_str(),"%d is the root",&x);//sscanf是c的函数,不可以直接用string,string是个类,要转换成char*
if(a[0]==x)puts("T");
else puts("F");
}
if(s.find("siblings")!=string::npos)
{
int x,y;sscanf(s.c_str(),"%d and %d are siblings",&x,&y);
int id1=finds(x),id2=finds(y);
if(id1>id2)swap(id1,id2);
if((id1-1)/2==(id2-1)/2)puts("T");
else puts("F");
}
if(s.find("parent")!=string::npos)
{
int x,y;sscanf(s.c_str(),"%d is the parent of %d",&x,&y);
int id=finds(x);
if(a[id*2+1]==y || a[id*2+2]==y)puts("T");
else puts("F");
}
if(s.find("child")!=string::npos)
{
int x,y;sscanf(s.c_str(),"%d is a child of %d",&x,&y);
int id=finds(y);
if(a[id*2+1]==x || a[id*2+2]==x)puts("T");
else puts("F");
}
}
}
L2-020 功夫传人 (25 分)(递归求解)
【分析】得道者的倍数用一个数组存起来,普通弟子用二维vector存起来;然后如果某个x的size为0,则为得道者,进行sum的求和;否则,继续递归下去找得道者即可;
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
vector<int>v[maxn];
int n;
double z,r;
double dfs(int x,int t)
{
double sum=0;
if(!v[x].size())sum+=a[x]*z*pow((1-0.01*r),t);
else
{
for(int i=0;i<v[x].size();++i)
sum+=dfs(v[x][i],t+1);
}
return sum;
}
int main()
{
scanf("%d%lf%lf",&n,&z,&r);
for(int i=0;i<n;++i)
{
int k;scanf("%d",&k);
if(k==0)scanf("%d",&a[i]);
else{
while(k--)
{
int x;scanf("%d",&x);
v[i].push_back(x);
}
}
}
double sum=dfs(0,0);
printf("%d\n",(int)sum);
}
L2-022 重排链表 (25 分)(结构体运用+有一个小坑)
【分析】注意是有结点不在链表上的.....
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
struct node{
int adr;
int val;
int nxt;
}a[maxn];
vector<int>v;
int main()
{
int adr,n;scanf("%d%d",&adr,&n);
for(int i=0;i<n;++i)
{
int adr,key,nxt;
scanf("%d%d%d",&adr,&key,&nxt);
a[adr].adr=adr;a[adr].nxt=nxt;a[adr].val=key;
}
for(int i=adr;i!=-1;i=a[i].nxt)
v.push_back(i);
int l=v.size();//cout<<"l="<<l<<endl;
int i;
for(i=l-1;i>l/2;--i)
{
printf("%05d %d %05d\n",v[i],a[v[i]].val,a[v[l-i-1]].adr);
printf("%05d %d %05d\n",v[l-i-1],a[v[l-i-1]].val,a[v[i-1]].adr);
}
if(i==l/2)
{
if(l&1)printf("%05d %d -1\n",v[i],a[v[i]].val);
else{
printf("%05d %d %05d\n",v[i],a[v[i]].val,a[v[l-i-1]].adr);
printf("%05d %d -1\n",v[l-i-1],a[v[l-i-1]].val);
}
}
}
L2-028 秀恩爱分得快 (25 分)(模拟+两种方法)
【分析】一个大模拟题..? 一上来就想的是非常暴力的解法,虽然觉得可能会T,但是还是想试试,然后,100来行,很必然地超时了....
想过先把照片的数据先存起来,但是没有处理好,再次T 【就百度了一下
先把照片信息存起来,记录每张照片的人数和各自的性别(注意0的处理,如果是-0那么性别是设置为-1的,所以要字符串读入);
然后输入情侣,再遍历照片信息,只记录有这两个人存在的照片
还要注意精度问题,除了之后要再乘上一个数,(不乘的话只有17分...和我T的代码一个分数诶..)
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
struct node{
int k;
int photo[maxn];
int vis[maxn];
}a[maxn];
int sex[maxn];
int val1[maxn],val2[maxn];
int n,m;
void print(int x,int y)
{
if(!x && sex[x]==-1)printf("-0 ");
else printf("%d ",x*sex[x]);
if(!y && sex[y]==-1)printf("-0\n");
else printf("%d\n",y*sex[y]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i)
{
int k;scanf("%d",&k);
a[i].k=k;
for(int j=0;j<k;++j)
{
string str;cin>>str;
int x=stoi(str);
if(x<0)x=-x;
a[i].photo[j]=x;
a[i].vis[x]=1;
if(str[0]=='-')sex[x]=-1;
else sex[x]=1;
}
}
string str1,str2;cin>>str1>>str2;
int A=stoi(str1),B=stoi(str2);
if(str1[0]=='-')A=-A,sex[A]=-1;
else sex[A]=1;
if(str2[0]=='-')B=-B,sex[B]=-1;
else sex[B]=1;
int f1=0,f2=0;
for(int i=0;i<m;++i)
{
if(a[i].vis[A])
{
f1=1;
for(int j=0;j<a[i].k;++j)
{
int x=a[i].photo[j];
if(x!=A && sex[x]+sex[A]==0)
val1[x]+=500*1.0/a[i].k;//,cout<<"1="<<x<<endl;
}
}
if(a[i].vis[B])
{
f2=1;
for(int j=0;j<a[i].k;++j)
{
int x=a[i].photo[j];
if(x!=B && sex[x]+sex[B]==0)
val2[x]+=500*1.0/a[i].k;//,cout<<"2="<<x<<endl;;
}
}
}
set<int>s1,s2;
int maxx1=0,maxx2=0;
for(int i=0;i<n;++i)
{
if(val1[i]>maxx1 && f1)
{
s1.clear();
s1.insert(i);
maxx1=val1[i];
}
else if(val1[i]==maxx1 && f1)
s1.insert(i);
if(val2[i]>maxx2 && f2)
{
s2.clear();
s2.insert(i);
maxx2=val2[i];
}
else if(val2[i]==maxx2 && f2)
s2.insert(i);
}
if(maxx1==maxx2 && maxx1==val1[B] && maxx2==val2[A])print(A,B);//注意这里maxx1和maxx2不仅要相等而且是要对应彼此的
else
{
set<int>::iterator it;
for(it=s1.begin();it!=s1.end();++it)
print(A,*it);
for(it=s2.begin();it!=s2.end();++it)
print(B,*it);
}
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int f[2][maxn];
int e[maxn][510];
int sex[maxn],num[maxn];
void print(int x,int y)
{
if(!x && sex[x]==-1)printf("-0");
else printf("%d",x*sex[x]);
printf(" ");
if(!y && sex[y]==-1)printf("-0");
else printf("%d",y*sex[y]);
puts("");
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=0;i<=1;i++)for(int j=0;j<n;++j)f[i][j]=0;
for(int k=1;k<=m;++k)
{
scanf("%d",&num[k]);
for(int i=1;i<=num[k];++i)
{
char s[10];scanf("%s",s);
if(s[0]=='-')
{
e[k][i]=-atoi(s);
sex[e[k][i]]=-1;
}
else
{
e[k][i]=atoi(s);
sex[e[k][i]]=1;
}
}
}
string s1,s2;cin>>s1>>s2;
int x=stoi(s1),y=stoi(s2);
if(s1[0]=='-')x=-x,sex[x]=-1;
else sex[x]=1;
if(s2[0]=='-')y=-y,sex[y]=-1;
else sex[y]=1;
for(int k=1;k<=m;++k)
{
for(int i=1;i<=num[k];++i)
if(e[k][i]==x)
{
for(int j=1;j<=num[k];++j)
{
if(sex[e[k][i]]+sex[e[k][j]]==0)
f[0][e[k][j]]+=500.0/num[k]*100;
//cout<<e[k][j]<<","<<f[0][e[k][j]]<<"--\n";
}
}
for(int i=1;i<=num[k];++i)
if(e[k][i]==y)
{
for(int j=1;j<=num[k];++j)
{
if(sex[e[k][i]]+sex[e[k][j]]==0)
f[1][e[k][j]]+=500.0/num[k]*100;
//cout<<e[k][j]<<","<<f[1][e[k][j]]<<"-----\n";
}
}
}
int maxx1=0,maxx2=0;
for(int i=0;i<n;++i)maxx1=max(maxx1,f[0][i]);
for(int i=0;i<n;++i)maxx2=max(maxx2,f[1][i]);
// cout<<maxx1<<","<<maxx2<<endl;
if(maxx1==f[0][y] && maxx2==f[1][x])print(x,y);
else{
for(int i=0;i<n;++i)
if(f[0][i]==maxx1 && sex[i]+sex[x]==0)print(x,i);
for(int i=0;i<n;++i)
if(f[1][i]==maxx2 && sex[y]+sex[i]==0)print(y,i);
}
return 0;
}