Problem A. The Last Word
贪心。每次加入新的字符时,比较当前字符与生成的串的首字符的大小关系,如果当前字符不小于首字符,加在开头,否则加在结尾。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
string str;
int main(){
freopen("A-large.in","r",stdin);
freopen("A-large.out","w",stdout);
int t;
cin>>t;
int cas = 0;
while(t--){
cas++;
cin>>str;
deque<char> ans;
int len = str.size();
for(int i=0;i<len;i++){
if(i==0){
ans.push_back(str[i]);
}else{
if(str[i]>=ans[0]){
ans.push_front(str[i]);
}else{
ans.push_back(str[i]);
}
}
}
printf("Case #%d: ",cas);
for(char ch:ans){
cout<<ch;
}
cout<<endl;
}
return 0;
}
Problem B. Rank and File
为输入的数计数,找出出现了奇数次的那些数,排序输出即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
bool cnt[2555];
int main(){
freopen("B-large.in","r",stdin);
freopen("B-large.out","w",stdout);
int t;
cin>>t;
int cas = 0;
while(t--){
cas++;
int n;
cin>>n;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<2*n;i++){
for(int j=1;j<=n;j++){
int hh;
scanf("%d",&hh);
cnt[hh] = !cnt[hh];
}
}
vector<int> ans;
for(int i=1;i<=2500;i++){
if(cnt[i]){
ans.push_back(i);
}
}
sort(ans.begin(),ans.end());
printf("Case #%d:",cas);
for(int h:ans){
printf(" %d",h);
}
cout<<endl;
}
return 0;
}
Problem C. BFFs
首先,小数据是可以dfs出来的。对于大数据,其实最优解只存在两种情况,要么是一个环(环是插不进去任何人的),要么由很多条链组成,每条链必有两个人互粉,然后其他人接在这两个人后面。
第一种情况非常简单,只要找最大的环就行了。
第二种情况,先找出所有互粉的人,然后尝试在这些人身后,接最长的链,其实就是原图的边反向,然后dp一下DAG最长路。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int f[1111];
bool ban[1111];
int dp[1111];
int match[1111];
int n;
int fun(int u){
if(dp[u]){
return dp[u];
}
int res = 1;
for(int i=1;i<=n;i++){
if(match[i]==u)continue;
if(f[i]==u){
res = max(res,fun(i)+1);
}
}
dp[u] = res;
return res;
}
int ans = 0;
int main(){
freopen("C-large.in","r",stdin);
freopen("C-large.out","w",stdout);
int t;
cin>>t;
int cas = 0;
while(t--){
memset(ban,0,sizeof(ban));
memset(dp,0,sizeof(dp));
memset(match,0,sizeof(match));
cas++;
cin>>n;
for(int i=1;i<=n;i++){
cin>>f[i];
}
//环
ans = 0;
for(int i=1;i<=n;i++){
if(ban[i])continue;
int cur=i;
bool vis[1111];
memset(vis,0,sizeof(vis));
int tmp=0;
while(1){
vis[cur] = 1;
cur = f[cur];
tmp++;
if(cur==i){
while(1){
ban[cur] = 1;
cur = f[cur];
if(cur==i)break;
}
ans = max(ans,tmp);
break;
}
if(vis[cur]){
break;
}
}
}
//若干条链
memset(ban,0,sizeof(ban));
int ans2 = 0;
for(int i=1;i<=n;i++){
if(ban[i])continue;
if(f[f[i]]==i){
ban[i]=1;
ban[f[i]]=1;
match[i] = f[i];
match[f[i]] = i;
ans2+=2;
}
}
for(int i=1;i<=n;i++){
if(ban[i]){
ans2+=fun(i)-1;
}
}
printf("Case #%d: ",cas);
cout<<max(ans,ans2)<<endl;
}
return 0;
}
本文解析了三道编程竞赛题目:TheLastWord通过贪心算法确定字符串排列;RankandFile统计并输出出现次数为奇数的整数;BFFs问题通过DFS和DP解决社交网络中好友匹配的最大数量。
1433

被折叠的 条评论
为什么被折叠?



