A. Prison Break
显然对矩阵四个角分别对
(
r
,
w
)
(r,w)
(r,w)求距离取最大值即可。
代码实现
#include <iostream>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int main()
{
int t; cin >> t;
while(t--)
{
int n, m, r, c;cin >> n >> m >> r >> c;
int ans = abs(n-r) + abs(m-c);
ans = std::max(ans, r+c-2);
ans = std::max(ans, r+abs(m-c)-1);
ans = std::max(ans, c+abs(n-r)-1);
cout << ans << endl;
}
}
B. Repainting Street
因为颜色至多只有一百种,暴力枚举剩下来的颜色即可。
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
int a[100100], c[105];
int main()
{
int t; cin >> t;
while (t--)
{
int n, k; cin >> n >> k;
memset(c, 0, sizeof(c));
for (int i = 0; i < n; ++i)
{
cin >> a[i];
c[a[i]]++;
}
int ans = 1001000;
for(int i = 1; i <= 100; ++i)
{
if(c[i]==0) continue;
int cnt = 0;
for (int p = 0; p < n; p+=k, cnt++)
{
while(a[p]==i) p++;
if(p >= n) break;
}
ans = min(ans, cnt);
}
cout << ans << endl;
}
}
C. Bouncing Ball
我们首先枚举最后一个点的位置。
对每一个枚举的最后一个点的位置向前回溯,也就是说每次回退k个位置。
每当我们到达一个位置,有四种可能性:
- 这个位置小于p。此时,无论如何操作皆无解。
- 这个位置等于p。此时,这就是第一个跳进来的点,只需要再判断下这个点有无平台即可。
- 这个位置大于p但是小于p+k。此时,这个点在经过一次回溯就将成为第一种情况。但是我们可以通过删除j-p个点来使得这个点可以被第一次跳进来时抵达。
- 这个点大于等于p+k。此时这个点可以往前继续回溯,也可以删除j-p个点来使其第一次跳跃时可以被抵达。记得要判断有无平台,没有的话花费要加x。
最后对每种可能的花费取最小值即可。
显然每个点最多被到达一次,所以时间复杂度是
O
(
n
)
O(n)
O(n)。
代码实现
#include <iostream>
#include <algorithm>
using namespace std;
string s;
int main()
{
int t; cin >> t;
while(t--)
{
int n, p, k; cin >> n >> p >> k;
cin >> s;
int x, y; cin >> x >> y;
int ans = 0x3fffffff;
for(int i = n-k; i < n; i++)
{
int j = i;
int cost = 0;
while(j>=0)
{
if(j<p-1)
{
cost = 1001000;
break;
}
if(j==p-1)
if(s[j]=='1') break;
else
{
cost += x;
break;
}
else if(j<p-1+k)
{
if(s[j]=='1');
else cost += x;
cost += (j-p+1) * y;
break;
}
else
{
if(s[j]=='1');
else cost += x;
ans = min(ans,(j-p+1) * y + cost);
j -= k;
}
}
ans = min(ans, cost);
}
cout << ans << endl;
}
}
D. XOR-gun
因为涉及异或操作,请把每个数字看作一个01字符串。
显然当有三个及三个以上的最高位相同的数字时,只要将其中两个异或,得到的值就会小于第三个值。
而题目给出的范围是 每个数字可被有符号四字节的整型存储。
根据鸽巢原理,只要n大于等于63,必定有答案为1的解。
也就是说,我们把数据规模减小到了63以下。
剩下的问题,我们交给暴力即可。
代码实现
#include <iostream>
#include <algorithm>
using namespace std;
int a[100100];
int main()
{
int n; cin >> n;
for(int i =1; i<=n; ++i) cin >> a[i];
int ans = 1001000;
if(n>=63) ans = 1;
else
{
for(int i = 1; i < n; ++i)
{
if(a[i+1]>=a[i]<<1) continue;
int j = i-1, temp = a[i], cnt = 0;
while(j>=1)
{
temp ^= a[j];
cnt++;
if(temp > a[i+1])
{
ans = min(ans, cnt);
break;
}
j--;
}
}
for(int i = n; i > 1; --i)
{
int j = i+1, temp = a[i], cnt = 0;
int b[100]= {0};
b[1] = a[i-1], b[0]++;
int k = i-2;
while(k >= 1 && b[a[0]] < b[b[0]] ^ a[k])
{
b[b[0]+1] = b[b[0]] ^ a[k];
b[0]++;
k--;
}
while(j<=n)
{
temp ^= a[j];
cnt++;
int flag = 0;
for(int x=1; x<=b[0]; x++)
{
if(temp < b[x])
{
cnt += x-1;
flag = 1;
break;
}
}
if(flag)
{
ans = min(ans, cnt);
break;
}
j++;
}
}
}
if(ans == 1001000)
cout << -1 << endl;
else cout << ans << endl;
}