2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) (B, D, G, H)
目录
21.1.30 2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016)
F 裸区间DP,gcd预处理下。I 网络流签到题。
迷惑的一场,8题两个多小时做完就只能划水了。
B. Foosball Dynasty √
/*
简单模拟 拿个queue
*/
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
using namespace std;
typedef long long LL;
const int N=1e3+5;
char s[N];
string name[N];
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
int main()
{
int n=read();
for(int i=1; i<=n; ++i) std::cin>>name[i];
scanf("%s",s+1); int m=strlen(s+1);
static std::queue<int> q;
for(int i=5; i<=n; ++i) q.push(i);
int now=0,wo=1,bo=2,wd=3,bd=4,mx=0,las=-1;//las=0:W las=1:B
for(int i=1; i<=m; ++i)
if(s[i]=='B')
{
if(las==1) ++now;
else now=1;
las=1, mx=std::max(mx,now);
std::swap(bo,bd);
q.push(wd), wd=wo, wo=q.front(), q.pop();
}
else
{
if(las==0) ++now;
else now=1;
las=0, mx=std::max(mx,now);
std::swap(wo,wd);
q.push(bd), bd=bo, bo=q.front(), q.pop();
}
int ans=mx; while(!q.empty()) q.pop();
for(int i=5; i<=n; ++i) q.push(i);
now=0,wo=1,bo=2,wd=3,bd=4,mx=0,las=-1;//las=0:W las=1:B
for(int i=1; i<=m; ++i)
if(s[i]=='B')
{
if(las==1) ++now;
else now=1;
las=1;
std::swap(bo,bd);
if(now==ans)
{
int a=now&1?bo:bd,b=now&1?bd:bo;
if(now==i) std::swap(a,b);
std::cout<<name[a]<<' '<<name[b]<<'\n';
}
q.push(wd), wd=wo, wo=q.front(), q.pop();
}
else
{
if(las==0) ++now;
else now=1;
las=0;
std::swap(wo,wd);
if(now==ans)
{
int a=now&1?wo:wd,b=now&1?wd:wo;
if(now==i) std::swap(a,b);
std::cout<<name[a]<<' '<<name[b]<<'\n';
}
q.push(bd), bd=bo, bo=q.front(), q.pop();
}
return 0;
}
D. Lost in Translation(BFS) √
深度要最小:用BFS!深度最小时可以更新dis。
怎么就容易忘了最简单的那种BFS分层呢。(注意一下状态数)
//31ms 4000KB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
using namespace std;
typedef long long LL;
const int N=1e5+5;
bool vis[N];
int dep[N];
LL dis[N];
struct Node2
{
int x,dep;
LL val;
};
struct Node{
int to,val;
};
vector<Node> e[N];
map<string,int> mp;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
int main()
{
int n=read()+1,m=read();
string s="English",t; mp[s]=1;
for(int i=2; i<=n; ++i) cin>>s, mp[s]=i;
int tot=n;
for(int i=1,u,v,w; i<=m; ++i)
{
cin>>s, cin>>t;
u=mp[s], v=mp[t], w=read();
e[u].push_back((Node){v,w}), e[v].push_back((Node){u,w});
}
static std::queue<Node2> q;
LL ans=0; q.push((Node2){1,0,0});
memset(dis,0x3f,sizeof dis);
for(int i=1; i<=n; ++i) dep[i]=N;
while(!q.empty())
{
Node2 p=q.front(); q.pop();
int x=p.x;
dep[x]=std::min(dep[x],p.dep);
if(p.dep==dep[x]) dis[x]=std::min(dis[x],p.val);
if(vis[x]) continue;
vis[x]=1;
for(auto v:e[x])
q.push((Node2){v.to,p.dep+1,v.val});
}
for(int i=1; i<=n; ++i)
if(!vis[i]) return puts("Impossible"),0;
else ans+=dis[i];
printf("%lld\n",ans);
return 0;
}
G. That's One Hanoi-ed Teacher(汉诺塔递归)
需要复习一下汉诺塔。汉诺塔的递归是这样的:
void DFS(int n,int a,int b,int c)//第n个圆盘从a->c
{
if(n==1)
{
printf("%d: %d->%d\n",n,a,c);
return;
}
DFS(n-1,a,c,b);
printf("%d: %d->%d\n",n,a,c);
DFS(n-1,b,a,c);
}
总过程是,将圆盘\(n-1\)从\(a\)移到\(b\),将圆盘\(n\)从\(a\)移到\(c\),最后将圆盘\(n-1\)从\(b\)移到\(c\)。
所以这个题,从\(n\)开始判断:
- 如果\(n\)仍在\(a\)上,则还至少需\(1\)步将\(n\)移到\(c\),和\(2^{n-1}-1\)步将\(n-1\)个盘子从\(b\)移到\(c\),然后再看\(n-1\)是否已经从\(a\)移到\(b\)上;
- 如果\(n\)在\(b\)上,则不是最优解;
- 如果\(n\)在\(c\)上,则\(n-1\)已到过\(b\),再看\(n-1\)是否已从\(b\)移到\(c\)即可。
类似地递归一下,注意修改当前的参数\(a,b,c\)就可以了。
//30ms 0KB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=105;
int vis[N];
LL ans;
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
bool DFS(int n,int a,int b,int c)
{
if(!n) return 1;
if(vis[n]==a) return ans+=1ll<<(n-1),DFS(n-1,a,c,b);//n还在a,判断n-1是否已从a移到b去
else if(vis[n]==c) return DFS(n-1,b,a,c);//n已经到c,判断n-1是否已从b移回到c去
return 0;
}
int main()
{
int a=read(); for(int i=1; i<=a; ++i) vis[read()]=1;
int b=read(); for(int i=1; i<=b; ++i) vis[read()]=2;
int c=read(); for(int i=1; i<=c; ++i) vis[read()]=3;
if(!DFS(a+b+c,1,2,3)) puts("No");
else printf("%lld\n",ans);
return 0;
}
H. Vin Diagrams(模拟) √
因为限制条件很多,所以直接从A
和B
位置开始DFS,求出每个X
属于的方阵,然后再对方阵里面的点DFS。至于交,可以先分别DFS整个A方阵和B方阵中的点,被DFS两次的点即交。
然后想找到A或B方阵中的某个点,可以找到方阵的左上角\((i,j)\),那么\((i+1,j+1)\)一定在该方阵中,从它开始DFS即可。
//30ms 400KB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
#define OK(x,y) (x>=1 && x<=n && y>=1 && y<=m)
typedef long long LL;
const int N=105,Way[5]={1,0,-1,0,1};//down,left,up,right
int n,m,Ans[5],bel[N][N];//1:A 2:B 3:intersection
char s[N][N];
int vis[N][N],vis2[N][N];
inline int read()
{
int now=0,f=1; char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
void DFS(int x,int y,int val,int pre)
{
int t=0;
for(int i=0; i<4; ++i)
{
int xn=x+Way[i],yn=y+Way[i+1];
if(OK(xn,yn)) t+=s[xn][yn]!='.';
}
if(t==4)
{
bel[x][y]=3;
for(int i=0; i<4; ++i)
if(i==pre)
{
int xn=x+Way[i],yn=y+Way[i+1];
if(OK(xn,yn)&&s[xn][yn]=='X'&&!bel[xn][yn]) DFS(xn,yn,val,i);
}
}
else
{
bel[x][y]=val, assert(t==2);
for(int i=0; i<4; ++i)
{
int xn=x+Way[i],yn=y+Way[i+1];
if(OK(xn,yn)&&s[xn][yn]!='.'&&(!bel[xn][yn]||bel[xn][yn]==3)) DFS(xn,yn,val,i);
}
}
}
void DFS2(int x,int y,int val)
{
vis[x][y]+=val, vis2[x][y]=1;
for(int i=0; i<4; ++i)
{
int xn=x+Way[i],yn=y+Way[i+1];
if(OK(xn,yn)&&bel[xn][yn]!=val&&bel[xn][yn]!=3&&!vis2[xn][yn]) DFS2(xn,yn,val);
}
}
void Calc(int val)
{
memset(vis2,0,sizeof vis2);
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)//找一个最左上角的,它的右下一定在封闭图形里面
if(bel[i][j]==val) {DFS2(i+1,j+1,val); return;}
}
int main()
{
int n=read(),m=read(); ::n=n, ::m=m;
for(int i=1; i<=n; ++i) scanf("%s",s[i]+1);
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
if(s[i][j]=='A'||s[i][j]=='B') DFS(i,j,s[i][j]=='A'?1:2,0);
Calc(1), Calc(2);
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j) if(!bel[i][j]) ++Ans[vis[i][j]];
printf("%d %d %d\n",Ans[1],Ans[2],Ans[3]);
return 0;
}
------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------