传送门

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&lt;&lt;j)]=min(d[i]+cnt[i])d[i| (1&lt;&lt;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]&gt;0b[i]&gt;0b[i]>0的点,肯定是构成了一个环。将所有b[i]=0b[i]=0b[i]=0的点,按照a[i]a[i]a[i]从小到大排序,然后就是iii向jjj连边(i&lt;j)(i&lt;j)(i<j);对于在环里的a[i]−b[i]&gt;0a[i]-b[i]&gt;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(部分题解,待补)相关推荐

  1. 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 ...

  2. 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 ...

  3. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest

    layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest author: "luow ...

  4. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)

    layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...

  5. 2021 Jiangsu Collegiate Programming Contest部分题解

    2021 Jiangsu Collegiate Programming Contest 目录 A. Spring Couplets C. Magical Rearrangement I. Fake W ...

  6. The 16th Heilongjiang Provincial Collegiate Programming Contest部分题解

    The 16th Heilongjiang Provincial Collegiate Programming Contest 目录 D - Doin' Time 题目思路 题目代码 F - Func ...

  7. Nordic Collegiate Programming Contest 2017 题解

    前几天打了一场外国人的比赛,感觉那边的题目质量还是很好的,区分度很鲜明,题目没有国内的难,坑点比较少,比较注重思维,基础算法. B题: Best Relay Team Picture by Ferna ...

  8. The 15th Chinese Northeast Collegiate Programming Contest部分题解

    The 15th Chinese Northeast Collegiate Programming Contest 目录 E. Easy Math Problem 题目思路 题目代码 I. Takea ...

  9. 2018 ACM-ICPC, Syrian Collegiate Programming Contest

    这是2018年叙利亚大学程序设计赛,星期一没什么比赛就拿这套题目练了一下手,在这里写几道我做出来的里面还算有点难度的题目(实力有限好多题看都没看) 比赛链接 http://codeforces.com ...

最新文章

  1. Android 5.0状态栏和导航栏
  2. 向HtmlAgilityPack道歉:解析HTML还是你好用
  3. CentOS6.4 添加播放×××
  4. 谈谈Java中的volatile
  5. 揭秘Kaggle神器xgboost
  6. 聊聊 Spring Cloud Config
  7. Solrj实现增删改查
  8. 编译php ./configure命令enable和with有什么区别
  9. ThreadLocal的学习
  10. linux tee 重定向_快乐的linux命令行-重定向
  11. LintCode,hihoCoder,LeetCode有什么区别?
  12. java抽象机制_Java很好学:接口+抽象类+事件监听机制
  13. win7下部署docker教程(三步搞定)
  14. htc思想[second]
  15. access mysql连接字符串_access 数据库连接字符串
  16. 笔记本无线上网怎么通过网线共享给台式机 设置方法
  17. 一键还原涂鸦图片_涂鸦的图片可以复原吗
  18. GNN algorithms(3): Tri-party Deep Network Representation
  19. 素材网站需要多大的服务器,网站图片一般多大尺寸
  20. 网络WIFI 无法连接 无法上网网络故障

热门文章

  1. 连续时间周期信号傅里叶级数
  2. 一阶、二阶和三阶随机占优
  3. Win2003 IIS6.0性能优化指南
  4. MCE公司:新型Kappa阿片受体拮抗剂和偏向性激动剂的发现
  5. elasticsearch forcemerge
  6. 2023江苏大学计算机考研信息汇总
  7. vue3 使用recorder-core 实现在线录制音频
  8. offer收割机: 字节跳动、YY、虎牙、BIGO
  9. 吃透浏览器安全(同源限制/XSS/CSRF/中间人攻击)
  10. 天翎携手群晖助力电商行业文档管理