目录
B - Go Straight and Turn Right
A - Last Letter
- 题意
给定一个字符串输出最后一个字符
- 思路:
语法题,见代码
- 时间复杂度 :
O(n)
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int n;
std::string s;
std::cin>>n>>s;
std::cout<<s[n-1];
return 0;
}
B - Go Straight and Turn Right
- 题意
小明在开始时站在(0,0)点
现给定一个字符串S,小明会根据字符串中的字母,按顺序执行操作:
- 若为'S',小明向前前进一个单位
- 若为'R',小明的朝向顺时针转动90度
- 思路:
模拟即可
- 时间复杂度 :
O(n)
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int n,ne[4][2] = {1,0,0,-1,-1,0,0,1};
int state = 0,x = 0,y = 0;
std::string s;
std::cin>>n>>s;
for(int i = 0 ; i < n ; i++)
{
if(s[i]=='S')
{
x += ne[state][0];
y += ne[state][1];
}
else
{
state++;
if(state==4)state = 0;
}
}
std::cout<<x<<" "<<y;
return 0;
}
C - Yamanote Line Game
- 题意
本题交互题:
规则:
给定一个数n,双方需要在1 ~( 2 * n + 1 )中选择一个数打印,之前打印过的数不能够再打印,直至其中一方找不到打印数为止。
- 思路:
用一个set存下所以可以打印的数,每次打印完就把这个数从set中删除,我们输出时,每次输出这个set的最小数即可。
- 时间复杂度 :
O(nlogn)
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;
int query()
{
int x;
std::cin>>x;
return x;
}
void solve()
{
int n;
std::cin>>n;
std::set<int> st;
for(int i = 1 ; i <= 2 * n + 1; i++)st.insert(i);
while(true)
{
std::cout<<*st.begin()<<std::endl;
st.erase(st.begin());
int x = query();
if(x==0)break;
st.erase(x);
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
// int T;
// std::cin>>T;
// while(T--)
{
solve();
}
return 0;
}
D - Swap Hats
- 题意
给三个人分别戴上三顶帽子,这三顶帽子为R B G。
初始时给定这三人戴帽子的情况,并给定三个人最终的戴帽子的情况。
现在可以交换两个人戴的帽子,执行 这个操作
次。
询问是否可以将初始状态变为最终状态。
- 思路:
显然不能模拟,我们可以讨论交换次数的奇偶性
存在三种情况:
- 初始状态和最终状态相同,那么可以通过不断交换1,2两个人的帽子保持偶数次操作时状态不变。(所以操作次数为偶数)
- 有两顶帽子不同,那么可以交换这两顶帽子,然后重复情况1。(操作次数为奇数)
- 有三顶帽子不同,那么可以两次操作变成情况1,重复1即可(操作次数为偶数)
操作次数为奇数,显然是"NO"
操作次数为偶数,显然是"YES"
- 时间复杂度 :
O(1)
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;
void solve()
{
char s[3],t[3];
for(int i = 0 ; i < 3 ; i++)std::cin>>s[i];
for(int i = 0 ; i < 3 ; i++)std::cin>>t[i];
int cnt = 0;
for(int i = 0 ; i < 3 ; i++)if(s[i]!=t[i])cnt++;
if(cnt==2)std::cout<<"No";
else std::cout<<"Yes";
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
// int T;
// std::cin>>T;
// while(T--)
{
solve();
}
return 0;
}
E - King Bombee
- 题意
给定一个无向图
求起点为S,终点为T,经过点数为K+1,其中点X的个数为偶数(可以为0)的路径数
- 思路:
我们尝试动态规划:
设
:
- dp的值是方案数
- i 表示的是当前已经经过的点数
- j 表示的是当前路径的最后一个点是 j
- k 表示的是这个路径中经过X次数的奇偶性(0为偶数,1为奇数)
那么初始状态为dp[1][S][0] = 1
答案为 dp[k+1][T][0]
状态转移为( u 为 j 相邻的点):
u == x:
u != x:
- 时间复杂度 :
要转移 i 次,每次转移都要遍历所有的边。
O(km)
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
const int N = 2e3+10,M = N * 2,INF = 0x3f3f3f3f,mod = 998244353;
int dp[N][N][2];
int h[N],e[M],ne[M],idx;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
memset(h,-1,sizeof h);
int n,m,k,S,T,x;
std::cin>>n>>m>>k>>S>>T>>x;
while(m--)
{
int a,b;
std::cin>>a>>b;
add(a,b),add(b,a);
}
dp[1][S][0] = 1;
for(int i = 2 ; i <= k + 1 ; i++)
{
for(int j = 1 ; j <= n ; j++)
{
if(dp[i-1][j][0]||dp[i-1][j][1])
{
for(int o = h[j] ; ~o ; o = ne[o])
{
int u = e[o];
if(u==x)
{
dp[i][u][0] = (dp[i][u][0] + dp[i-1][j][1]) % mod;
dp[i][u][1] = (dp[i][u][1] + dp[i-1][j][0]) % mod;
}
else
{
dp[i][u][0] = (dp[i][u][0] + dp[i-1][j][0]) % mod;
dp[i][u][1] = (dp[i][u][1] + dp[i-1][j][1]) % mod;
}
}
}
}
}
std::cout<<dp[k+1][T][0];
return 0;
}
F - Shortest Good Path
- 题意
对于某个边权均为 1 的无向图,给定所有只含有0和1的长度为n的字符串
对于某一个字符串,我们要寻找这样一条路径:
若
,则点 i 出现的次数应该为奇数
若
, 则点 i 出现的次数应该为偶数(可以为0)
对于某一种情况的字符串,计算这个路径的长度最小值
求出所有路径的和
- 思路:
有题目所给范围以及信息已知本题需要用状态压缩
设
:
- dp值为路径最小长度
- i 表示状态,第 k 位为0则代表点 k 出现次数为偶数,反之为奇数
- j 表示当前状态下当前所在点为 j
那么显然,所有点出现次数为偶数时,路径长最小值为0
当只有某个点出现次数为奇数时,路径最小长度为1
我们可以这些点为出发点,使用BFS,得到所有情况的最小值
答案可以表示为:
- 时间复杂度 :
因为是通过枚举邻边进行拓展,所以时间复杂度要乘m
AC代码:
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
const int N = 19,M = N * N,INF = 0x3f3f3f3f,mod = 998244353;
struct Node{
int state,u;
}que[(1<<N)*N];
int dp[1<<N][N];
int tail,head;
int h[N],e[M],ne[M],idx;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int n,m;
head = 0,tail = -1;
memset(h,-1,sizeof h);
memset(dp,0x3f,sizeof dp);
std::cin>>n>>m;
while(m--)
{
int a,b;
std::cin>>a>>b;
add(a,b),add(b,a);
}
dp[0][1] = 0;
for(int i = 0 ; i < n ; i++)
{
dp[1<<i][i+1] = 1;
que[++tail] = {1<<i,i+1};
}
while(tail>=head)
{
auto temp = que[head++];
for(int i = h[temp.u] ; ~i ; i = ne[i])
{
int u = e[i];
int state = temp.state ^ (1 << (u-1));
if(dp[state][u]==INF)
{
dp[state][u] = dp[temp.state][temp.u] + 1;
que[++tail] = {state,u};
}
}
}
int res = 0;
for(int i = 0 ; i < (1 << n) ; i++)
{
res += *std::min_element(dp[i]+1,dp[i]+n+1);
// std::cout<<*std::min_element(dp[i]+1,dp[i]+n+1)<<'\n';
}
std::cout<<res;
return 0;
}