2018 ACM-ICPC Syrian Collegiate Programming Contest(部分题解,待补)
传送门
2018 ACM-ICPC 叙利亚大学生程序设计竞赛
Problem A: Hello SCPC 2018!
签到题
Problem B: Binary Hamming
简单题
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
const int INF=1e9+7;
typedef long long ll;
char a[200],b[200];
int main()
{freopen("hamming.in","r",stdin);int T;cin>>T;while(T--){int n;scanf("%d",&n);scanf("%s%s",a,b);sort(a,a+n);sort(b,b+n);reverse(a,a+n);int ans=0;for(int i=0;i<n;i++)ans+=a[i]!=b[i];printf("%d\n",ans);}return 0;
}
Problem C: Portals
思路:主要是找出起点和终点左右两边的第一个可达的传送门,然后分类讨论,细节比较多。(也可以找出传送门后,枚举把哪些’.‘变成’#’,然后BFS)
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int INF=1e9+7;
typedef long long ll;
char s[MAX];
int check(int x,int y,char c)//找出x->y碰到的第一个c字符的位置
{if(x<=y){for(int i=x;i<=y;i++)if(s[i]==c)return i;}else{for(int i=x;i>=y;i--)if(s[i]==c)return i;}return 0;
}
int ask(int x,int y)
{if(x<=y){for(int i=x;i<=y;i++){if(s[i]=='#')return 0;if(s[i]=='o')return i;}}else{for(int i=x;i>=y;i--){if(s[i]=='#')return 0;if(s[i]=='o')return i;}}return 0;
}
int main()
{freopen("portals.in","r",stdin);int T;cin>>T;while(T--){int n,st,en;scanf("%d%s",&n,s+1);for(int i=1;i<=n;i++){if(s[i]=='s')st=i;if(s[i]=='e')en=i;}if(st>en)swap(st,en);if(check(st+1,en-1,'#')==0&&check(st+1,en-1,'.')==0){puts("-1");continue;}int sL=ask(st-1,1); //st左边第一个可达的传送门int sR=ask(st+1,en-1); //st右边第一个可达的传送门int eL=ask(en-1,st+1); //en左边第一个可达的传送门int eR=ask(en+1,n); //en右边第一个可达的传送门if(sR==0&&eL==0){if(check(st+1,en-1,'#')){if(sL==0||eR==0)puts("0");else if(sL==st-1&&eR==en+1)puts("-1");else puts("1");}else{if(sL==0||eR==0)puts("1");else if(sL==st-1&&eR==en+1)puts("-1");else puts("2");}}if(sR==0&&eL){if(sL==0&&eR==0)puts("0");if(sL==0&&eR)puts("0");if(sL&&eR==0){if(sL==st-1&&eL==en-1)puts("-1");else puts("1");}if(sL&&eR){if(sL<st-1)puts("1");else if(sL==st-1&&(eL==en-1||eR==en+1))puts("-1");else puts("2");}}if(sR&&eL==0){if(sL==0&&eR==0)puts("0");if(sL==0&&eR){if(sR==st+1&&eR==en+1)puts("-1");else puts("1");}if(sL&&eR==0)puts("0");if(sL&&eR){if(eR>en+1)puts("1");else if(eR==en+1&&(sL==st-1||sR==st+1))puts("-1");else puts("2");}}if(sR&&eL){if(sL==0&&eR==0){if(eL<en-1||sR>st+1)puts("1");else puts("-1");}if(sL&&eR==0){if((sL==st-1||sR==st+1)&&eL==en-1)puts("-1");else if(eL<en-1)puts("1");else puts("2");}if(sL==0&&eR){if((eL==en-1||eR==en+1)&&sR==st+1)puts("-1");else if(sR>st+1)puts("1");else puts("2");}if(sL&&eR){if((sL==st-1||sR==st+1)&&(eL==en-1||eR==en+1))puts("-1");else puts("2");}}}return 0;
}
Problem D: Carnival Slots
思路:贪心。按分数从大到小将列排序,然后从当前列开始向两边延伸。PS:因为一个沙雕错误错了几天,还一直没发现。顺带附上个人的一组数据:
3 6
1 1 1 1 1
\.\…
.\.\…
…\.\.
0 1 2 4 3 5
#include<bits/stdc++.h>
using namespace std;
const int MAX=510;
typedef long long ll;
int a[MAX],v[MAX];
ll b[MAX],c[MAX];
char s[MAX][MAX];
int cmp(const int&x,const int&y){return c[x]>c[y];}
int main()
{freopen("balls.in","r",stdin);int T;cin>>T;while(T--){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%lld",&b[i]);for(int i=1;i<=n;i++)scanf("%s",s[i]+1);for(int i=1;i<=m;i++)scanf("%lld",&c[i]);for(int i=1;i<=m;i++)a[i]=i;sort(a+1,a+m+1,cmp);memset(v,0,sizeof v);ll ans=0;for(int i=1;i<=m;i++){for(int j=n-1;j>=1;j--)s[j][a[i]]='.';if(v[a[i]]==0)ans+=b[a[i]]*c[a[i]];v[a[i]]=1;for(int x=a[i]-1,y=n;x>=1&&y>=1;x--,y--){while(y>0&&s[y][x]=='.')y--;if(y==0)break;for(int j=y;j>=1;j--)s[j][x]='.';if(v[x]==0)ans+=b[x]*c[a[i]];v[x]=1;}for(int x=a[i]+1,y=n;x<=m&&y>=1;x++,y--){while(y>0&&s[y][x]=='.')y--;if(y==0)break;for(int j=y;j>=1;j--)s[j][x]='.';if(v[x]==0)ans+=b[x]*c[a[i]];v[x]=1;}}printf("%lld\n",ans);}return 0;
}
Problem F: Pretests
思路:状压dp。d[i]d[i]d[i]表示已经排好了状态为iii的测试点。枚举接下来要选中的测试点jjj,则有:d[i∣(1<<j)]=min(d[i]+cnt[i])d[i| (1<<j)]=min(d[i]+cnt[i])d[i∣(1<<j)]=min(d[i]+cnt[i])其中cnt[i]cnt[i]cnt[i]为至少通过状态iii的所有测试点的人数。
即cnt[i]=∑jcnt[j](i∈j)cnt[i]=\sum_j cnt[j] (i\in j)cnt[i]=j∑cnt[j](i∈j)其中最难的部分是求cnt[i]cnt[i]cnt[i],我所知道的枚举子集的方法是O(t3)O(t^3)O(t3),用SOS DP可以优化到O(t∗2t)O(t*2^t)O(t∗2t)。
#include<bits/stdc++.h>
using namespace std;
const long long INF=1e9+7;
typedef long long ll;
char s[30];
ll cnt[1<<20];
ll d[1<<20];
string pre[1<<20];
int main()
{freopen("tests.in","r",stdin);int T;cin>>T;while(T--){int m,n;scanf("%d%d",&m,&n);for(int i=0;i<(1<<m);i++)cnt[i]=0;for(int i=0;i<(1<<m);i++)d[i]=INF;for(int i=0;i<(1<<m);i++)pre[i]="";for(int i=1;i<=n;i++){scanf("%s",s);int sum=0;for(int j=0;j<m;j++)sum+=(1<<j)*(s[j]-'0');cnt[sum]++;}//SOS dp预处理出cnt[i]for(int i=m-1;i>=0;i--)for(int j=(1<<m)-1;j>=0;j--){if((1<<i)&j)cnt[j^(1<<i)]+=cnt[j];}d[0]=0;for(int i=0;i<(1<<m);i++){for(int j=0;j<m;j++){if(i&(1<<j))continue;if(d[i]+cnt[i]<d[i^(1<<j)]){d[i^(1<<j)]=d[i]+cnt[i];pre[i^(1<<j)]=pre[i];pre[i^(1<<j)]+=j+1+'0';}else if(d[i]+cnt[i]==d[i^(1<<j)]){string a=pre[i];a+=j+1+'0';if(a<pre[i^(1<<j)])pre[i^(1<<j)]=a;}}}printf("%lld\n",d[(1<<m)-1]);for(int i=0;i<m;i++)printf("%d%c",pre[(1<<m)-1][i]-'0',i==m-1?'\n':' ');}return 0;
}
Problem G: Is Topo Logical?
思路:所有b[i]>0b[i]>0b[i]>0的点,肯定是构成了一个环。将所有b[i]=0b[i]=0b[i]=0的点,按照a[i]a[i]a[i]从小到大排序,然后就是iii向jjj连边(i<j)(i<j)(i<j);对于在环里的a[i]−b[i]>0a[i]-b[i]>0a[i]−b[i]>0的点,由环外的点向环内的点连边。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
const int MAX=2e5+10;
const double PI=acos(-1.0);
typedef long long ll;
vector<int>p,q;
int a[MAX],b[MAX];
int cmp(const int&x,const int&y){return a[x]<a[y];}
int check(int n)
{p.clear();q.clear();for(int i=1;i<=n;i++){if(b[i]!=0)q.push_back(i);else p.push_back(i);}sort(p.begin(),p.end(),cmp);if(q.size()>0&&(int)q.size()-1<*max_element(b+1,b+n+1))return 0;for(int i=0;i<p.size();i++)if(i<a[p[i]])return 0;for(int i=0;i<q.size();i++)if(a[q[i]]-b[q[i]]>(int)p.size())return 0;return 1;
}
int main()
{freopen("topo.in","r",stdin);int T;cin>>T;while(T--){int n,ans=0;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=n;i++)scanf("%d",&b[i]);if(check(n)==0){puts("-1");continue;}for(int i=1;i<=n;i++)ans+=a[i];printf("%d\n",ans);for(int i=q.size()-1;i>=0;i--)printf("%d %d\n",q[(i-1+(int)q.size())%(int)q.size()],q[i]);for(int i=0;i<q.size();i++)for(int j=i+1;j<i+b[q[i]];j++)printf("%d %d\n",q[j%(int)q.size()],q[i]);for(int i=0;i<q.size();i++)for(int j=0;j<a[q[i]]-b[q[i]];j++)printf("%d %d\n",p[j],q[i]);for(int i=0;i<p.size();i++)for(int j=0;j<a[p[i]];j++)printf("%d %d\n",p[j],p[i]);}return 0;
}
Problem H: Bugged System
思路:因为要保证每个人最后都没有付钱,那么每个人的起点是另一个人的终点,最后形成一个环。如果形成了环,那么最短路就是所有人的路径和;否则输出-1。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
ll x[MAX];
int a[MAX];
int main()
{freopen("bugged.in","r",stdin);int T;cin>>T;while(T--){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lld",&x[i]);for(int i=1;i<=n;i++)a[i]=0;ll ans=0;for(int i=1;i<=m;i++){int L,R;scanf("%d%d",&L,&R);a[L]++;a[R]--;ans+=abs(x[R]-x[L]);}for(int i=1;i<=n;i++)if(a[i]!=0)ans=-1;printf("%lld\n",ans);}return 0;
}
Problem I: Rise of the Robots
思路:因为要求所有的点均在桌内且保证有解,先假设起点为(0,0)(0,0)(0,0),那么我们可以求出一个半径最小的圆,恰好把机器人所有经过的点(包括起点)包含进去,然后我们就可以求出圆心,那么我们只要移动这个圆,使其圆心和原点重合即可。
那么起点也要移动相同的向量。
#include<bits/stdc++.h>
using namespace std;
const int MAX=300;
struct Point{double x,y;}p[MAX],ans;
Point operator+(Point A,Point B){return (Point){A.x+B.x,A.y+B.y};}
double operator*(Point A,Point B){return A.x*B.x+A.y*B.y;}
double dis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
int n;
double cal(double x,double y)
{double sum=0;for(int i=0;i<=n;i++)sum=max(sum,dis((Point){x,y},p[i]));return sum;
}
double cal(double x)
{double l=-100000,r=100000;for(int i=1;i<=100;i++){double mid=(l+r)/2;double m=(mid+r)/2;if(cal(x,mid)>cal(x,m))l=mid;else r=m;}return cal(x,(l+r)/2);
}
int main()
{freopen("robots.in","r",stdin);int T;cin>>T;while(T--){int R,R1;scanf("%d%d%d",&n,&R,&R1);p[0]={0,0};for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);for(int i=1;i<=n;i++)p[i]=p[i-1]+p[i];double l=-R,r=R;for(int i=1;i<=100;i++)//三分求出包含所有点的最小圆的圆心{double mid=(l+r)/2;double m=(mid+r)/2;if(cal(mid)>cal(m))l=mid;else r=m;}ans.x=(l+r)/2;l=-R,r=R;for(int i=1;i<=100;i++){double mid=(l+r)/2;double m=(mid+r)/2;if(cal(ans.x,mid)>cal(ans.x,m))l=mid;else r=m;}ans.y=(l+r)/2;printf("%.9f %.9f\n",-ans.x,-ans.y);}return 0;
}
Problem K: Tourists’ Tour
思路:先建好图,用单调栈即可。然后就是如何涂色的问题了,可以想到所用的颜色种类不会很多(其实最多为3种),然后我们把图改为有向图,即高点向低点连边,然后按照拓扑排序对各个点进行涂色。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
vector<int>e[MAX];
int h[MAX],in[MAX];
int v[MAX];
int c[MAX][4];
void init(int n)
{stack<int>p;for(int i=1;i<=n;i++)e[i].clear();for(int i=1;i<=n;i++)in[i]=0;while(!p.empty())p.pop();for(int i=1;i<=n;i++){while(!p.empty()&&h[p.top()]<=h[i])p.pop();if(!p.empty())e[p.top()].push_back(i),in[i]++;p.push(i);}while(!p.empty())p.pop();for(int i=n;i>=1;i--){while(!p.empty()&&h[p.top()]<=h[i])p.pop();if(!p.empty())e[p.top()].push_back(i),in[i]++;p.push(i);}for(int i=1;i<=n;i++)for(int j=0;j<=3;j++)c[i][j]=0;
}
int main()
{freopen("tour.in","r",stdin);int T;cin>>T;while(T--){int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&h[i]);init(n);queue<int>p;for(int i=1;i<=n;i++)if(in[i]==0)p.push(i);int ans=0;while(!p.empty()){int x=p.front();p.pop();for(int i=1;i<=3;i++){if(c[x][i])continue;ans=max(ans,i);v[x]=i;for(int j=0;j<e[x].size();j++){int nex=e[x][j];c[nex][i]=1;in[nex]--;if(in[nex]==0)p.push(nex);}break;}}printf("%d\n",ans);for(int i=1;i<=n;i++)printf("%d%c",v[i],i==n?'\n':' ');}return 0;
}
2018 ACM-ICPC Syrian Collegiate Programming Contest(部分题解,待补)相关推荐
- 2018 ACM ICPC Arabella Collegiate Programming Contest A
Multiplication operation is not always easy! For example, it is hard to calculate 27 × 20 using your ...
- A - Multiplication Dilemma (思维)( 2018 ACM ICPC Arabella Collegiate Programming Contest)
滴答滴答---题目链接 Multiplication operation is not always easy! For example, it is hard to calculate 27 × 2 ...
- (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest
layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest author: "luow ...
- (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)
layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...
- 2021 Jiangsu Collegiate Programming Contest部分题解
2021 Jiangsu Collegiate Programming Contest 目录 A. Spring Couplets C. Magical Rearrangement I. Fake W ...
- The 16th Heilongjiang Provincial Collegiate Programming Contest部分题解
The 16th Heilongjiang Provincial Collegiate Programming Contest 目录 D - Doin' Time 题目思路 题目代码 F - Func ...
- Nordic Collegiate Programming Contest 2017 题解
前几天打了一场外国人的比赛,感觉那边的题目质量还是很好的,区分度很鲜明,题目没有国内的难,坑点比较少,比较注重思维,基础算法. B题: Best Relay Team Picture by Ferna ...
- The 15th Chinese Northeast Collegiate Programming Contest部分题解
The 15th Chinese Northeast Collegiate Programming Contest 目录 E. Easy Math Problem 题目思路 题目代码 I. Takea ...
- 2018 ACM-ICPC, Syrian Collegiate Programming Contest
这是2018年叙利亚大学程序设计赛,星期一没什么比赛就拿这套题目练了一下手,在这里写几道我做出来的里面还算有点难度的题目(实力有限好多题看都没看) 比赛链接 http://codeforces.com ...
最新文章
- Android 5.0状态栏和导航栏
- 向HtmlAgilityPack道歉:解析HTML还是你好用
- CentOS6.4 添加播放×××
- 谈谈Java中的volatile
- 揭秘Kaggle神器xgboost
- 聊聊 Spring Cloud Config
- Solrj实现增删改查
- 编译php ./configure命令enable和with有什么区别
- ThreadLocal的学习
- linux tee 重定向_快乐的linux命令行-重定向
- LintCode,hihoCoder,LeetCode有什么区别?
- java抽象机制_Java很好学:接口+抽象类+事件监听机制
- win7下部署docker教程(三步搞定)
- htc思想[second]
- access mysql连接字符串_access 数据库连接字符串
- 笔记本无线上网怎么通过网线共享给台式机 设置方法
- 一键还原涂鸦图片_涂鸦的图片可以复原吗
- GNN algorithms(3): Tri-party Deep Network Representation
- 素材网站需要多大的服务器,网站图片一般多大尺寸
- 网络WIFI 无法连接 无法上网网络故障