是回文,我玩了回文
A. Rearranging ABC
题目给定了由三个大写英文字母组成的字符串S,要求判断其是否可以通过改变字母顺序的方式,将字符串S修改为"ABC"。
十分甚至九分的简单(那你还用了十分钟???),我的思路是判断是否出现A或B或C,出现一次即cnt+特定的值,A-1,B-10,C-100;不写方便的A-1,B-2,C-3,是因为这样可以保证不会出现奇奇怪怪凑好数的情况,比如BBB。
下面是我的代码:
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
string s; int cnt = 0;
cin >> s;
for(int i = 0; i < 3; i++){
if (s[i] == 'A')
{
cnt += 1;
}
else if (s[i] == 'B')
{
cnt += 10;
}
else if (s[i] == 'C')
{
cnt += 100;
}
else;
}
if (cnt == 111) cout << "Yes";
else cout << "No";
return 0;
}
我已经爱上了ios这行魔法咒语。
B. Avoid Rook Attack
字面翻译过来就是别被车吃了。这套题跟国际象棋有关系。下面是这道题的题意:
车可以吃其所在的行和列上所有的棋子。
现在用"·"表示空格,用"#"表示车;在8*8的格子里,按从上到下排序,给你第一行到第八行,一共八个字符串,字符串表示该行"·""#"交错的这么个状态,即该行“空格”和“车”的分布状态。
现在让你放棋子,要求既不能放在车的上面,又不能放在车的攻击范围内,问你最多能放几个。
我的解题思路是:
int两个数组代表x和y,注意xy取第四象限的坐标轴
先row y,看看哪一行有车,记下来;然后继续row y,只不过这一次嵌套一个row x,记一下哪一列有车,而且八行不分开记,全写到一个数组里,重叠位置。
然后你就能反向得出哪一行哪一列没有车;统计得到哪几行哪几列没有车,接着就可以将行和列的数一乘,这就是结果了。
下面是我的代码:
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
string s; int ans = 0;
int x[10] = {0}; int y[10] = {0};
int xcnt = 0; int ycnt = 0;
for (int i = 0; i < 8; i++)
{
cin >> s;
for (int j = 0; j < 8; j++)
{
if (s[j] == '#')
{
y[i] = 1;
x[j] = j + 1;
}
}
}
for (int i = 0; i < 8; i++)
{
if (x[i] == 0)
xcnt++;
if (y[i] == 0)
ycnt++;
}
ans = xcnt*ycnt;
cout << ans;
return 0;
}
C. Avoid Knight Attack
题意又绕了点。
给你一个n*n的方格,上面放了m个马,这个国际象棋里的马是走日的,但是很别扭。
A piece placed on square (i,j)(i,j) can capture pieces that satisfy any of the following conditions:
- Placed on square (i+2,j+1)
- Placed on square (i+1,j+2)
- Placed on square (i−1,j+2)
- Placed on square (i−2,j+1)
- Placed on square (i−2,j−1)
- Placed on square (i−1,j−2)
- Placed on square (i+1,j−2)
- Placed on square (i+2,j−1)
跟B一样,不能放在马上,不能放在攻击范围内,问你最多能放几个棋子。
这个题我的思维是开一个范围更大的数组,然后从数组偏中间的位置写入,周围留一圈空白值,以防止数组越界。然后按照那八个条件手动赋值。最后判断有多少数可行。
然后就爆掉了,3221225725。
这里十分感谢zyc老师,&ls教的真好,&ls的代码写得真好。
#include <bits/stdc++.h>
typedef long long ll;
const ll N=10000005;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll n , m;
std::map <std::pair<ll,ll> , bool> mapp;
ll dx[8] = {-2 , -1 , 1 , 2 , 2 , 1 , -1 , -2};
ll dy[8] = {1 , 2 , 2 , 1 , -1 , -2 , -2 , -1};
void solve(){
std::cin >> n >> m;
ll ans = 0;
for (ll i = 1; i <= m; i++){
ll x , y;
std::cin >> x >> y;
std::pair <ll , ll> ppp = std::make_pair(x , y);
if(mapp[ppp] == false) ans++;
mapp[ppp] = true;
for (ll j = 0; j <= 7; j++){
ll nx = dx[j] + x;
ll ny = dy[j] + y;
if (nx <= n && nx >= 1 && ny >=1 && ny <=n){
std::pair <ll , ll> pp = std::make_pair(nx , ny);
if(mapp[pp] == false) ans++;
mapp[pp] = true;
}
}
}
std::cout << n * n - ans << '\n';
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ll t = 1; //std::cin >> t;
while (t--) solve();
return 0;
}
我们来 厚颜无耻地抄袭 解析一下:
typedef long long 属于是省事了。然后定义常量N跟INF,INF这里很讨巧地使用0x3f3f3f3f3f3f3f3f,正好比数据边界小一。这好像是一个系列,0x3f~0x3f3f3f3f3f3f3f3f都有。
开一个map叫mapp,key是pair,value是bool。接着用dx, dy分别存贮偏移量,也就是以马为参考系,马的攻击范围相对于马位置的偏移量。
然后void一个函数叫solve。
在solve里输入马位置的x, y坐标;造一个pair叫ppp,把x, y组合成一组数据;接下来就借助mapp判断,ppp对应的bool是真还是假,是假就ans++,真就啥也不干。
这个地方需要注意,map中对bool的默认值是false,所以写入的数据会是false。
这一段操作是统计,马所在位置的数量。
我想知道为什么不能直接用ans += m,然后我试了,在过第三个样例的时候数据不对,小了个1。我不明白。是因为pp位置跟ppp重了?不应该啊?
判断完成后,无论是真是假,将mapp中任意pair对应的bool一律定义为真,防止重复计数。
再然后来个for循环,先if判断防止过界;开一个名叫pp的map,对没过界的数据进行make_pair处理。
接着if判断,pp对应的bool是真还是假,是假就ans++,真就啥也不干。判断完成后,无论是真是假,将pp中任意pair对应的bool一律定义为真,防止重复计数。
最后把总数减去ans,得到结果。
下面主函数无非就是个壳子,保障运行罢了。
小结
想打赢复活赛就给我老老实实练习,基本算法跟stl用起来!!!
小插曲:塔罗可能会带来不幸。