F
题目来源
简述:
- 一共有n+1个村庄,2n-1条小路
- 其中有n-1条小路是顺序连接着村庄1-2-3-4-5……n
- (第 n+1个村庄被孤立)
- 再有n条小路,通过数组ai存储0和1描述它们的连接方式
- 0:代表小路从村庄i指向村庄n+1
- 1:代表小路从村庄n+1指向村庄i
- 问可以单向连接所有村庄的方式(输出一种)
解析
- 简图如下
- 考虑以下三种情况
- a[1]==1 (n+1)~(1)~(2)~ ...~ (n)
- a[n]==0 (1)~(2)~ ...~(n)~(n+1)
- a[k]==0&&a[k+1]==1 (1)~(2)~...~(k)~(n+1)~(k+1)~...~(n)
只要满足上述三个情况之一则可以输出一条路径
否则输出-1
代码段
void solve()
{
int n;
cin >> n;
vector<int>a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
if (a[1] == 1)
{
cout << n + 1 << ' ';
for (int i = 1; i <= n;i++)
cout << i << ' ';
return;
}
else if (a[n] == 0)
{
for (int i = 1; i <= n + 1; i++)
cout << i << ' ';
return;
}
for (int i = 1; i < n; i++)
{
if (a[i] == 0 && a[i + 1] == 1)
{
for (int j = 1; j <= i; j++)
cout << j << ' ';
cout << n + 1 << ' ';
for (int j = i + 1; j <= n; j++)
cout << j<< ' ';
return;
}
}
cout << -1 << endl;
}
G
题目来源
简述
- 总共有1-10 10个球,奇数球a队踢,偶数球b队踢
- 如果是 1 ,则进球
- 如果是0 则不进球
- 如果是? 未知
- 问最少踢多少球就可以不用比下去了
- 某队得分>另一只队的得分+剩下的点球数
解析
- 既然要求最少的场数,我们不妨将某一队的不确定的场数看作是全进球
- 首先假设b队(偶数球)问号场全进,比较当b>a-(10-i)/2(假设剩余的场数全进)
- 更新最小情形
- 再假设a队(奇数球)问号场全进,比较当a>b-(10-i+1)/2(假设剩余的场数全进)
- 更新最小情形
代码段
void solve()
{
string s;
cin >> s;
int a = 0, b = 0,ans=10;
int size = s.size();
for (int i = 0; i < size; i++)
{
if ((i+1)& 1)
{
if (s[i] == '1')a++;
}
else
{
if (s[i] == '1' || s[i] == '?')
b++;
}
if (b > a + (10 - i-1) / 2)
{
ans = min(ans,i+1);
}
}
a = 0, b = 0;
for (int i = 0; i < size; i++)
{
if (1 & (i+1))
{
if (s[i] == '1'||s[i] == '?')a++;
}
else
{
if (s[i] == '1')
b++;
}
if (a > b + (10 - i ) / 2)
{
ans = min(ans,i+1);
}
}
cout << ans << endl;
}
H
题目来源
简述
- 给出两个字符串s1,s2
- 要求对s1进行操作之后得到s2
- 操作内容:
- 如果对第一个字符操作,即删去第一个字符
- 其他字符操作,删去此字符与前面一个字符,一次清除两个
解析
- 首先我们将两个字符串倒置(相当于逆向遍历)
- 然后使用双指针
- i指向a,pos指向b
- 在i向后遍历并寻找a[i]==b[pos]的同时清除不匹配的情况
- 注意一次清除两个字符
- 直到在a[i]中找到全部的b中的字符则可以输出
- 这么操作的合理性在于
- 首先如果我们遇到在b中不存在的字符,是一定要删去并且删两个,毫无疑问
- 对于当前b[pos]我们在a中寻找到的第一个满足的字符a[i],我们就将它保留下来
- 合理性在于
- 对于下一个我们要在a中寻找的字符a[j],它与a[i]之间即使存在一个a[k]==b[pos],我们选择保留a[i]和a[k]是一样的
- 举例:字符串1:ckckb 字符串2:cb
- 保留第一个c后面b就会被删除,保留第二个c(第一个被删除),后面b依旧会被删除
- 举例:字符串1:ckckcb 字符串2:cb
- 保留第一个c,能够组成cb。保留第二个c(删除第一个),依旧能组成cb
- 所以保留哪个符合的字符都可以,不妨就直接保存最先遇到的
代码段
void solve()
{
string a, b;
cin >> a >> b;
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int pos = 0;
for (int i = 0; i < a.size(); i++)
{
if (a[i] == b[pos])pos++;
else i++;
if (pos == b.size())break;
}
puts(pos == b.size() ? "YES" : "NO");
}