A. SwapSort
思路:从大到小对每个位置,如果它上面的数不是当前最大的,就随便找一个最大的换过去。这题坑了我好久,没看到不用找最小swap次数。。。
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
int a[3010];
int b[3010];
int main(){
int n;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(b,b+n);
int ans=0;
vector<int> swa;
for(int i=n-1;i>0;i--){
if(a[i]==b[i])continue;
for(int j=0;j<i;j++){
if(b[i]==a[j]){
swap(a[i],a[j]);
ans++;
swa.push_back(j);
swa.push_back(i);
break;
}
}
}
cout<<ans<<endl;
for(int i=0;i<ans;i++){
cout<<swa[i*2]<<" "<<swa[i*2+1]<<endl;
}
}
return 0;
}
B. BerSU Ball
思路:先计数,然后扫一遍,把能配对的全配对了就行。
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
int cntB[110];
int cntG[110];
int main(){
int n,m;
cin>>n;
for(int i=0;i<n;i++){
int t;
cin>>t; cntB[t]++;
}
cin>>m;
for(int i=0;i<m;i++){
int t;
cin>>t; cntG[t]++;
}
int ans=0;
for(int i=1;i<=100;i++){
while(cntB[i]&&cntG[i-1]){
cntB[i]--;
cntG[i-1]--;
ans++;
}
while(cntB[i]&&cntG[i]){
cntB[i]--;
cntG[i]--;
ans++;
}
while(cntB[i]&&cntG[i+1]){
cntB[i]--;
cntG[i+1]--;
ans++;
}
}
cout<<ans<<endl;
return 0;
}
C. Given Length and Sum of Digits...
思路:为了使数合法,先在最高位置1,然后暴力从低位/高位加数即可。需要特判一下和为0长度为1的情况。
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
int ans1[110];
int ans2[110];
int main(){
int m,s;
while(cin>>m>>s){
memset(ans1,0,sizeof(ans1));
memset(ans2,0,sizeof(ans2));
if(m==1&&s==0){
cout<<"0 0"<<endl;
continue;
}
ans1[1]=1;
int tmp=s-1;
for(int i=m;i>=1;i--){
while(ans1[i]<9){
if(tmp<=0)break;
ans1[i]++;
tmp--;
}
if(tmp<=0)break;
}
if(tmp!=0){
cout<<-1;
}else{
for(int i=1;i<=m;i++){
cout<<ans1[i];
}
}
cout<<" ";
ans2[1]=1;
tmp=s-1;
for(int i=1;i<=m;i++){
while(ans2[i]<9){
if(tmp<=0)break;
ans2[i]++;
tmp--;
}
if(tmp<=0)break;
}
if(tmp!=0){
cout<<-1;
}else{
for(int i=1;i<=m;i++){
cout<<ans2[i];
}
}
cout<<endl;
}
return 0;
}
D. Unbearable Controversy of Being
思路:枚举起点,走两步,记cnt[i]为某个起点两步走到i的方法数,结果加上cnt[i]*(cnt[i]-1)/2。注意走两步后不要回到起点。
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define ll long long
vector<int> E[3010];
ll cnt[3010];
int main(){
int n,m;
while(cin>>n>>m){
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
}
ll ans=0;
for(int k=1;k<=n;k++){
memset(cnt,0,sizeof(cnt));
queue<int> que;
int siz=E[k].size();
for(int i=0;i<siz;i++){
que.push(E[k][i]);
}
while(!que.empty()){
int cur=que.front(); que.pop();
int siz=E[cur].size();
for(int i=0;i<siz;i++){
if(E[cur][i]!=k)cnt[E[cur][i]]++;
}
}
for(int i=1;i<=n;i++){
if(cnt[i]>1){
ans+=cnt[i]*(cnt[i]-1)/2;
}
}
}
cout<<ans<<endl;
}
return 0;
}