LDU 2020级国庆七天乐第1天部分题解
F . Figure Skating
题目描述:
给出预测排名和最终排名,如果最终没有人比预测排名好,则输出“suspicious”;否则打印最终排名比预测排名上升最多的选手的名字
思路:
这题没什么难度,主要是结构体的简单应用:n1记录预测,n2记录最终;
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
struct str{
int nu1,nu2,up;
string name;
};
int main() {
int n,flag=0;
str ss[maxn];
string a,p;
cin>>n;
for(int i=1;i<=n;i++) {cin>>ss[i].name;ss[i].nu1=i;}
for(int i=1;i<=n;i++) {
cin>>a;
for(int j=1;j<=n;j++){
if(ss[j].name==a){
ss[j].nu2=i;
break;
}
}
}
for(int i=1;i<=n;i++){
if(ss[i].nu2>ss[i].nu1){
flag=1;
break;
}
}
if(!flag) cout<<"suspicious"<<endl;
else {
int p,maxx=-1000000000;
for(int i=1;i<=n;i++){
ss[i].up=ss[i].nu1-ss[i].nu2;
if(ss[i].up>maxx) {maxx=ss[i].up;p=i;}
}
cout<<ss[p].name<<endl;
}
return 0;
}
G . Group Project
题目描述:
看了很久才明白题意。总的来说是把两个班的n人分为两个大组,两个班之间会有m对不融洽关系,求最后能两两配对的最大对数(两两配对肯定能相互融洽)。
题目中说了保证能分成两个组,使这两个组里的成员都相互融洽==
所以,求出两个大组的各自人数,再分别除以2,就可以得到对数了。注意一种特殊情况,即:当两个大组都为奇数个人数的时候,可能会有第一个大组最后剩余的一个人会和第二个大组最后剩余的一个人配对的情况(他们虽然在两个不同的大组中,但可以相处融洽)
思路:
并查集来求两个大组,最后会一定可以组成两个并查集大组(题目说了保证能分成两个大组的),如果a有敌人,则让a的敌人和b 结合,否则 记录a的敌人是b;同样,如果b有敌人,则让b的敌人和a 结合,否则 记录b的敌人是a;(敌人的敌人就是朋友)
x记录第一个大组人数,y记录第二个大组人数;
x%2&&y%2&&x*y!=m 则说明了 第一个组中会有一个人和第二个组中的一个人相处融洽并且配对(比如第一组3人,第二组5人,第一组中的人与第二组中的人 如果都不能相处融洽,那么不融洽对数是3×5=15对,如果不是15,那么两组一定会选出各有一人相处融洽),配对数加1。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int pre[maxn],d[maxn];
int Find(int x){
if(pre[x]==x) return x;
return pre[x]=Find(pre[x]);
}
void combine(int x,int y){
int dx=Find(x),dy=Find(y);
if(dx!=dy) pre[dx]=dy;
}
int main(){
int n,m,a,b;
cin>>n>>m;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++){
cin>>a>>b;
if(d[a]) combine(d[a],b);
else d[a]=b;
if(d[b]) combine(d[b],a);
else d[b]=a;
}
int x=0,y=0;
for(int i=1;i<=n;i++){
if(Find(i)==Find(1)) x++; //Find(1)保证是其中一个大组的成员之一,x++;
else y++;//否则,另一个组的成员个数 y++;
}
int cnt=x/2+y/2;
if(x%2&&y%2&&x*y!=m) cnt++;
cout<<cnt;
return 0;
}
还有一种方法是二分图染色法
链接: 在这.
H . Human Pyramid
此题用到三维DP,本人ruoji一个,大佬们请点链接自行理解
链接: 点这里.
I . In-place Sorting
题目描述:
询问是否可以通过将‘6’变为‘9’或‘9’变为‘6’的形式,将下列按顺序排列的数字,变为非递减的序列,可能的话还要输出序列
思路:
虽然是数字,但用字符串,修改比较方便。
先将第一个数字中的‘9’都改为‘6’,为的是使第一个数字尽可能小;
再从第二个数开始比较字符
1)个数比上一个数字字符个数小,肯定不会大于上个数字,退出。
2)个数比上一个数字字符个数大,把这个数字中的‘9’都改为‘6’,使这个数字尽可能小,让下一个数字有最大可能比这一个数字大;
3)字符个数相等。这时,把数字中的‘6’改为‘9’,如果‘6’都改为‘9’后还比上一个数字小,肯定不会大于上一个数字。否则,开始循环跑,从数字左边开始将‘9’先变为‘6’,如果变为‘6’比上一个数字小了,则再把这个‘6’改为‘9’,保证比上一个数字大;
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
string s[maxn];
void solve(string &str){
for(int i=0;i<str.size();i++)
if(str[i]=='6')
str[i]='9';
return ;
}
void solve1(string &str){
for(int i=0;i<str.size();i++)
if(str[i]=='9')
str[i]='6';
return ;
}
int main() {
int n,flag=1,f;
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
solve1(s[1]);
for(int i=2;i<=n;i++){
if(s[i].size()<s[i-1].size()) {flag=0;break;}
else if(s[i].size()>s[i-1].size()){
solve1(s[i]);
}else{
solve(s[i]);
if(s[i]<s[i-1]){flag=0;break;}
else{
for(int j=0;j<s[i].size();j++){
if(s[i][j]=='9'){
s[i][j]='6';
if(s[i]<s[i-1]) s[i][j]='9';
}
}
}
}
}
if(!flag) cout<<"impossible"<<endl;
else{
cout<<"possible"<<endl;
for(int i=1;i<=n;i++)
cout<<s[i]<<endl;
}
return 0;
}
J . Jam-packed
题目描述:
要把n个罐子放进箱子里,一个箱子最多装k个罐子,一个箱子里罐子越少罐子越容易破裂,为避免这样,希望罐数最少的盒子尽可能装满,求最后装最少罐子的箱子里的罐子数。
思路:
我想最后肯定每个箱子里罐子越平均,才能让罐数最少的盒子尽可能装满,于是先求能放完k个罐子的盒子数,再 罐子数/盒子数得到平均值
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
int main() {
ll n,k;
cin>>n>>k;
ll a=n/k;
if(n%k) a++;
cout<<n/a;
return 0;
}
K . Kangaroo Commotion
想了很久也不会。。此题用到bfs变式
请看学长代码:
链接: 戳这.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=2e7+7;
int n,m,k;
char s[100][100];
bool mp[N];
int dx[9]={0,0,0,1,-1,-1,-1,1,1};
int dy[9]={0,1,-1,0,0,-1,1,-1,1};
struct node{
int x,y,vx,vy,k,d;
node(int x,int y,int vx,int vy,int k,int d):x(x),y(y),vx(vx),vy(vy),k(k),d(d){}
bool cc(){
if(x<1||y<1||x>n||y>m||s[x][y]=='#') return 0;
if(abs(vx)>7||abs(vy)>7) return 0;
return 1;
}
int hash(){ return x+y*50+(vx+8)*50*50+(vy+8)*50*50*15+(k+1)*50*50*15*15; }
};
node go(node i,int dx,int dy){
i.vx+=dx; i.vy+=dy;
i.x+=i.vx; i.y+=i.vy;
i.d++;
return i;
}
queue<node>q;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
scanf("%s",&s[i][1]);
for(int j=1;j<=m;j++){
if(s[i][j]=='0'){
q.push(node(i,j,0,0,1,0));
mp[q.front().hash()]=1;
}
}
}
while(!q.empty()){
node pre=q.front(); q.pop();
for(int i=0;i<9;i++){
node u=go(pre,dx[i],dy[i]);
if(!u.cc()) continue;
if(u.k==s[u.x][u.y]-'0') u.k++;
if(u.k==k+2&&s[u.x][u.y]-'0'==k+1&&u.vx==0&&u.vy==0){
printf("%d",u.d);
return 0;
}
int v=u.hash();
if(mp[v]) continue;
q.push(u); mp[v]=1;
}
}
printf("impossible");
}