A:Broadcast Stations

留坑。

B:Connect3

题意:四个栈,每次放棋子只能放某个栈的栈顶,栈满不能放,现在给出(1, x) 表示黑子放在第x个栈的第一个位置,白子放在第b个栈的第a个位置并且是胜利局势的情况有几种,只要有三个相同的连在一起就是赢了

思路:数据很小,暴力搜索即可,注意判重。

 #include <bits/stdc++.h>

 using namespace std;

 int x, a, b;

 int G[][];

 // 0 not done
// 1 white
// 2 black inline string Hash()
{
string ans = "";
for (int i = ; i <= ; ++i)
for (int j = ; j <= ; ++j)
{
ans += G[i][j] + '';
}
return ans;
} map <string, bool> mp; int cnt[]; inline bool ok(int x, int y)
{
if (x < || x > || y < || y > ) return false;
return true;
} int Move[][] =
{
, ,
, -,
, ,
-, ,
-, -,
-, ,
, -,
, ,
}; inline bool check(int x, int y)
{
int color = G[x][y];
for (int i = ; i < ; ++i)
{
int nx = x + Move[i][];
int ny = y + Move[i][];
int nnx = nx + Move[i][];
int nny = ny + Move[i][];
if (ok(nx, ny) && ok(nnx, nny))
if (G[nx][ny] == color && G[nnx][nny] == color)
return true;
nx = x + Move[i][];
ny = y + Move[i][];
nnx = x - Move[i][];
nny = y - Move[i][];
if (ok(nx, ny) && ok(nnx, nny))
if (G[nx][ny] == color && G[nnx][nny] == color)
return true;
}
return false;
} int tot; inline void DFS(int x, int y, int vis)
{
if (check(x, y))
{
if (vis == ) return;
if (x == b && y == a)
{
string s = Hash();
if(mp[s] == false)
{
mp[s] = true;
tot++;
}
}
return;
}
// if (x == b && y == a)
// {
// if (check())
// {
// string s = Hash();
// if (mp[s] == false)
// {
// mp[s] = true;
// tot++;
// }
// }
// return;
// }
for (int i = ; i <= ; ++i)
{
if (cnt[i] < )
{
cnt[i]++;
G[i][cnt[i]] = vis;
DFS(i, cnt[i], vis == ? : );
G[i][cnt[i]] = ;
cnt[i]--;
}
}
} inline void Init()
{
memset(cnt, , sizeof cnt);
memset(G, , sizeof G);
mp.clear();
tot = ;
} int main()
{
while (scanf("%d%d%d", &x, &a, &b) != EOF)
{
Init();
cnt[x]++; G[x][] = ;
DFS(x, , );
cout << tot << endl;
}
}

C:Game Map

题意:给出n个点,以及m条无向边,然后两个点之间如果有边那么度数大的那个点可以走到度数小的那个点,求最后从任意一个点出发,最远能走的路径的长度。

思路:显然,重新建图之后两个点之间最多有一个边,那么显然是若干棵树的结构,树形DP即可

 #include<bits/stdc++.h>

 using namespace std;

 #define N 100010
#define M 1000010 struct node{
int v,nx;
inline node(){}
inline node(int v,int nx) :v(v), nx(nx){}
}G[M]; int n, m;
int head[N], vis[N], dp[N], du[N], ans;
int tot; inline void init()
{
tot = ;
memset(head, -, sizeof head);
memset(vis, , sizeof vis);
memset(dp, , sizeof dp);
memset(du, , sizeof du);
} inline void addedge(int u,int v)
{
G[tot] = node(v, head[u]);
head[u] = tot++;
G[tot] = node(u, head[v]);
head[v] = tot++;
} inline void DFS(int u)
{
dp[u] = ;
vis[u] = ;
int tmp = ;
for(int i = head[u]; ~i; i = G[i].nx)
{
int v = G[i].v;
if(du[v] > du[u])
{
if(!vis[v]) DFS(v);
tmp = max(tmp, dp[v]);
}
}
dp[u] += tmp;
ans = max(ans, dp[u]);
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
init();
for(int i = ; i <= m; ++i)
{
int u,v;
scanf("%d %d",&u,&v);
addedge(u, v);
du[u]++;
du[v]++;
}
for(int i = ; i < n; ++i)
{
if(!vis[i]) DFS(i);
}
printf("%d\n", ans);
}
return ;
}

D:Happy Number

水。

 #include <bits/stdc++.h>

 using namespace std;

 map <int, bool> mp;

 int n;

 inline int Get(int x)
{
int tot = ;
while (x)
{
int num = x % ;
tot += num * num;
x /= ;
}
return tot;
} inline bool solve()
{
mp.clear();
while (true)
{
int num = Get(n);
if (num == ) return true;
n = num;
if (mp[num] == true)
return false;
mp[num] = true;
}
} int main()
{
while (scanf("%d", &n) != EOF)
{
puts(solve() ? "HAPPY" : "UNHAPPY");
}
}

E:How Many to Be Happy?

题意:定义一个函数H(e), 如果一条边属于最小生成树,那么H(e) = 0, 如果不属于,那么H(e) = 删掉最少的边使得它是最小生成树的边数

思路:考虑最小生成树任意两点之间都相互连通,那么对于每一条边,我们需要知道这条边邻接的两点,在包含这条边以及权值比这条边小的所有边的图中的最小割是多少,对每一条边都这么跑一次最大流

 #include <bits/stdc++.h>

 using namespace std;

 #define N 110
#define M 510
#define INF 0x3f3f3f3f struct Edge
{
int to, nx, cap, flow;
inline Edge() {}
inline Edge(int to, int nx, int cap, int flow) : to(to), nx(nx), cap(cap), flow(flow) {}
}edge[M << ]; int head[N], tol; inline void Init()
{
tol = ;
memset(head, -, sizeof head);
} inline void addedge(int u, int v, int w)
{
edge[tol] = Edge(v, head[u], w, ); head[u] = tol++;
edge[tol] = Edge(u, head[v], w, ); head[v] = tol++;
} int Q[N];
int dep[N], cur[N], sta[N]; inline bool BFS(int s, int t, int n)
{
int front = , tail = ;
memset(dep, -, sizeof (dep[]) * (n + ));
dep[s] = ;
Q[tail++] = s;
while (front < tail)
{
int u = Q[front++];
for (int it = head[u]; ~it; it = edge[it].nx)
{
int v = edge[it].to;
if (edge[it].cap > edge[it].flow && dep[v] == -)
{
dep[v] = dep[u] + ;
if (v == t) return true;
Q[tail++] = v;
}
}
}
return false;
} inline int Dinic(int s, int t, int n)
{
int maxflow = ;
while (BFS(s, t, n))
{
for (int i = ; i < n; ++i) cur[i] = head[i];
int u = s, tail = ;
while (cur[s] != -)
{
if (u == t)
{
int tp = INF;
for (int i = tail - ; i >= ; --i)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
maxflow += tp;
for (int i = tail - ; i >= ; --i)
{
edge[sta[i]].flow += tp;
edge[sta[i] ^ ].flow -= tp;
if (edge[sta[i]].cap - edge[sta[i]].flow == )
tail = i;
}
u = edge[sta[tail] ^ ].to;
}
else if (cur[u] != - && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + == dep[edge[cur[u]].to])
{
sta[tail++] = cur[u];
u = edge[cur[u]].to;
}
else
{
while (u != s && cur[u] == -)
u = edge[sta[--tail] ^ ].to;
cur[u] = edge[cur[u]].nx;
}
}
}
return maxflow;
} struct node
{
int u, v, w;
inline void scan()
{
scanf("%d%d%d", &u, &v, &w);
u--, v--;
}
inline bool operator < (const node& r) const
{
return w < r.w;
}
}G[M]; int n, m; int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = ; i <= m; ++i)
G[i].scan();
sort(G + , G + + m);
int ans = ;
for (int i = ; i <= m; ++i)
{
Init();
for (int j = ; j < i; ++j)
{
if (G[j].w >= G[i].w)
break;
addedge(G[j].u, G[j].v, );
}
ans += Dinic(G[i].u, G[i].v, n);
// cout << G[i].u << " " << G[i].v << " " << ans << endl;
}
cout << ans << endl;
}
return ;
}

F:philosopher's Walk

题意:给出n=2^k,m<=2^2k。对于一个n*n的图,输出第m个点的坐标。

思路:因为每个n*n的图由4个全等的(n/2)*(n/2)的图组成,所以采用分治的思想,每次算出目标点在4块图的那一块,记录那块图的坐标。

但是因为子图的方向不一样,所以要在计算出第几块图之后,要根据之前的方向判断这块图在左上,左下,右上,右下那个位置。

 #include<bits/stdc++.h>

 using namespace std;

 int main() {
long long n,m,x,y,t,p,q;
while (scanf("%lld %lld",&n,&m)!=EOF)
{
x=y=; t=;
while (n>) {
q=n*n/;
p=(m-)/q+;
m=(m-)%q+;
if (t==) {
if (p==) {t=;}
else if (p==) {y+=(n/);}
else if (p==) {x+=(n/); y+=(n/);}
else if (p==) {x+=(n/); t=;}
}
else if (t==) {
if (p==) {t=;}
else if (p==) {x+=(n/);}
else if (p==) {x+=(n/); y+=(n/);}
else if (p==) {y+=(n/); t=;}
}
else if (t==) {
if (p==) {x+=(n/); y+=(n/); t=;}
else if (p==) {x+=(n/);}
else if (p==) {y+=(n/); t=;}
}
else if (t==) {
if (p==) {x+=(n/); y+=(n/); t=;}
else if (p==) {y+=(n/);}
else if (p==) {x+=(n/); t=;}
}
n/=;
}
printf("%lld %lld\n",x,y);
}
return ;
}

G:Rectilinear Regions

留坑。

H:Rock Paper Scissors

留坑。

I:Slot Machines

题意:寻找下标为k长度为p的循环节,使得k+p最小,在k+p相同时保证p小。

思路:倒过来寻找,Next[i]记录上一个和这一位数字相同的下标。每次寻找都找前一位的Next中其中一位,并且保证这一位后面与当前节点值相同,从而保证了Next数组里面记录了循环的初始节点,最后扫一遍即可。

 #include<bits/stdc++.h>

 using namespace std;

 #define N 1000010
#define INF 0x3f3f3f3f int n;
int arr[N], nx[N]; int main()
{
while(~scanf("%d",&n))
{
memset(nx, , sizeof nx);
for(int i = n; i >= ; --i)
{
scanf("%d", arr + i);
}
for(int i = ; i <= n; ++i)
{
int tmp = nx[i - ];
while(tmp != && arr[i] != arr[tmp + ])
tmp = nx[tmp];
if(arr[i] == arr[tmp + ])
tmp++;
nx[i] = tmp;
}
int sum = INF;
int ansk = ;
int ansp = ;
for(int i = ; i <= n; ++i)
{
int k = n - i;
int p = i - nx[i];
if(k + p < sum)
{
sum = k + p;
ansk = k;
ansp = p;
}
else if(sum == k + p && p < ansp)
{
ansk = k;
ansp = p;
}
}
printf("%d %d\n",ansk, ansp);
}
return ;
}

J:Strongly Matchable

留坑。

K:Untangling Chain

题意:给出n个线段,每次给出线段的长度和转向的方向 1 表示左转,-1 表示右转,可以修改线段的长度,长度为(1 -> n) 使得所有线段不相交

思路: 按照类似这样的方法构造一下,每次的长度最多+1,长度最大为n,符合题意。 图中只是一个方向的实例,构造的图不一定是这样,但是思路是这样。

 #include <bits/stdc++.h>

 using namespace std;

 int n;

 int up, down, l, r;
int x, y, dir; // 0 up 1 left 2 down 3 right int main()
{
while (scanf("%d", &n) != EOF)
{
up = down = l = r = ;
x = y = dir = ;
int len, num;
for (int i = ; i <= n; ++i)
{
scanf("%d%d", &len, &num);
dir = (dir + ) % ;
if (dir == )
{
len = up - y + ;
y += len;
up = max(up, y);
}
else if (dir == )
{
len = x - l + ;
x -= len;
l = min(l, x);
}
else if (dir == )
{
len = y - down + ;
y -= len;
down = min(down, y);
}
else if (dir == )
{
len = r - x + ;
x += len;
r = max(r, x);
}
printf("%d%c", len , " \n"[i == n]);
dir += num;
}
}
return ;
}

J:Vacation Plans

留坑。


赛后总结:

  • 如果开了某一题但是没有思路,读新题的优先级高于一切
  • 比赛过程尽量不要懈怠,不一定无题可做, 不要从心里上战败
  • 做题要看清数据范围,算一算时间复杂度,有些题确实可以爆搜
  • 写题的时候,如果开了两个一样的东西,一定要万分注意,要知道什么时候用哪个
  • 当没有什么思路的时候,模拟一下题意过程是比较好的一个方式
  • 一道题如果没有思路,但是感觉像某种算法的题,可以考虑弃题,不要停留太久浪费时间,读新题
  • 对于题面又臭又长的题目,一定要耐心下来读
  • 当一题队友在敲,但是思维有一点阻碍时,可以适当放下手中事,帮队友理清一下思路可能会更好
  • 构造题有时候要大胆,但是构造题以及猜想题没有百分百把握下,不可开场做

2017-2018 ACM-ICPC, Asia Daejeon Regional Contest Solution的更多相关文章

  1. ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków

    ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...

  2. 2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)

    2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred) easy: ACE ...

  3. 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest PART(10/12)

    $$2017-2018\ ACM-ICPC,\ Asia\ Daejeon\ Regional\ Contest$$ \(A.Broadcast\ Stations\) \(B.Connect3\) ...

  4. 2018-2019, ICPC, Asia Yokohama Regional Contest 2018 K

    传送门:https://codeforces.com/gym/102082/attachments 题解: 代码: /** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ...

  5. 2018 ICPC Asia Jakarta Regional Contest

    题目传送门 题号 A B C D E F G H I J K L 状态 Ο . . Ο . . Ø Ø Ø Ø . Ο Ο:当场 Ø:已补 .  :  待补 A. Edit Distance Thin ...

  6. Gym - 101981K The 2018 ICPC Asia Nanjing Regional Contest K.Kangaroo Puzzle 暴力或随机

    题面 题意:给你1个20*20的格子图,有的是障碍有的是怪,你可以每次指定上下左右的方向,然后所有怪都会向那个方向走, 如果2个怪撞上了,就融合在一起,让你给不超过5w步,让所有怪都融合 题解:我们可 ...

  7. Gym - 101981M The 2018 ICPC Asia Nanjing Regional Contest M.Mediocre String Problem Manacher+扩增KMP

    题面 题意:给你2个串(长度1e6),在第一个串里找“s1s2s3”,第二个串里找“s4”,拼接后,是一个回文串,求方案数 题解:知道s1和s4回文,s2和s3回文,所以我们枚举s1的右端点,s1的长 ...

  8. Gym - 101981G The 2018 ICPC Asia Nanjing Regional Contest G.Pyramid 找规律

    题面 题意:数一个n阶三角形中,有多少个全等三角形,n<=1e9 题解:拿到题想找规律,手画开始一直数漏....,最后还是打了个表 (打表就是随便定个点为(0,0),然后(2,0),(4,0), ...

  9. Gym - 101981I The 2018 ICPC Asia Nanjing Regional Contest I.Magic Potion 最大流

    题面 题意:n个英雄,m个怪兽,第i个英雄可以打第i个集合里的一个怪兽,一个怪兽可以在多个集合里,有k瓶药水,每个英雄最多喝一次,可以多打一只怪兽,求最多打多少只 n,m,k<=500 题解:显 ...

随机推荐

  1. EOF ---shell编程

    转自:http://blog.163.com/njut_wangjian/blog/static/1657964252013112152418345/ 在shell编程中,”EOF“通常与”<& ...

  2. poj_2286 线段树

    题目大意 在墙上贴海报,墙壁是由一排连续的瓷砖铺成,海报贴在墙壁上必须占据连续的几块瓷砖,海报可以互相覆盖,问最后可以看见几张海报(未被完全覆盖). 题目分析 墙壁是由连续的一个区间构成,每个海报占据 ...

  3. GIT+ Coding使用方法

    1 进入码市 :https://coding.net    注册一个账户 2 创建一个项目: 3 本地window环境.安装git : https://git-scm.com/download/win ...

  4. Go基础---->go的基础学习(五)

    这里是go中关于io的一些知识.有时不是你装得天衣无缝,而是我愿意陪你演得完美无缺. go中关于io的使用 一.Reader中的Read方法 Read 用数据填充指定的字节 slice,并且返回填充的 ...

  5. c++ 引用底层实现

    红色是我添加的,其他地方是原作者的. 主要是看了上面的这篇“从底层汇编理解 c++ 引用实现机制“的文章之后,觉得不错.就转了过来,同时,对文中的程序都在自己的机器上验证了一下. 使用的G++版本:g ...

  6. OpenStack Cinder 与各种后端存储技术的集成叙述与实践

    先说下下loop设备 loop设备及losetup命令介绍 1. loop设备介绍 在类 UNIX 系统里,loop 设备是一种伪设备(pseudo-device),或者也可以说是仿真设备.它能使我们 ...

  7. python 多线程ping大量服务器在线情况

    需要ping一个网段所有机器的在线情况,shell脚步运行时间太长,用python写个多线程ping吧,代码如下: #!/usr/bin/python #coding=utf-8 ''' Create ...

  8. CentOS7安装步骤详解

    准备环境 1.虚拟机  VMware Workstation 2.Centos7-64位安装包  ( CentOS-6.7-x86_64-bin-DVD1.iso ) 开始安装   进入安装初始化界面 ...

  9. Flum入门必备知识

    1.flume概念 flume是分布式的,可靠的,高可用的,用于对不同来源的大量的日志数据进行有效收集.聚集和移动,并以集中式的数据存储的系统. flume目前是apache的一个顶级项目. flum ...

  10. Code Forces 18D Seller Bob(简单DP)

    D. Seller Bob time limit per test 2 seconds memory limit per test 128 megabytes input standard input ...