A. Game of Life
字符串模拟
毅神代码:
#include<bits/stdc++.h>
using namespace std;
string s;
char ans[1009];
int t ,n, m;
int main()
{
cin >> t;
while(t--)
{
cin >> n >> m >> s;
memset(ans,0,sizeof(ans));
for(int i = 0; i < n; ++i) ans[i] = s[i];
// 初始化
for(int i = 0; i < min(m,n); ++i)// 最多扩散 min(m,n)次
{
for(int j = 0; j < n; ++j)
if(s[j] == '0')// 每次判断一下0两边的情况
{
int f1 = 0, f2 = 0;
if(j && s[j-1] == '1') f1 = 1;
if(j != n-1 && s[j+1] == '1') f2 = 1;
if(f1&&f2);
else if(f1 || f2) ans[j] = '1';
}
// 因为每次扩散只每次的初始状态有关,所以不能边扩散边改
for(int j = 0 ; j < n; ++j) s[j] = ans[j];
}
ans[n] = '\0';
printf("%s\n",ans);
}
return 0;
}
我的垃圾代码:
和毅神思路不一样,他以死细胞为主,模拟扩散m次
我模拟的扩散的区间,只要能扩散到的都先变成1,最后打个补丁,只有在两个1的位置相加为偶数时,中间的那个死细胞不会激活
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 9;
typedef long long ll;
ll t = 1, n, m, r, k;
vector <pair<int,int> > v, vv;
//ll a[N];
char s[N];
int main()
{
cin >> t;
while(t--)
{
v.clear();vv.clear();
cin >> n >> m;
scanf("%s", s+1);
for(int i = 1; i <= n; ++i)
{
if(s[i] == '1')
{
int x, y;
if(i-m <= 0) x = 1;
else x = i - m;
if(i+m > n) y = n;
else y = i + m;
v.push_back(make_pair(x, y));
vv.push_back(make_pair(i-m,i+m));
}
}
if(!v.size())
{
printf("%s\n", s+1);continue;
}
//for(int i = 0; i < v.size(); ++i)
// cout << v[i].first << " " << v[i].second << " ";cout << endl;
if(v[0].first > 1)
{
for(int i = 1; i < v[0].first; ++i) s[i] = '0';
for(int i = v[0].first; i <= v[0].second; ++i) s[i] = '1';
}
else for(int i = 1; i <= v[0].second; ++i) s[i] = '1';
for(int i = 1; i < v.size() - 1; ++i)
{
if(v[i].first < v[i-1].second)
{
for(int j = v[i-1].second; j <= v[i].second; ++j) s[j] = '1';
}
else
{
for(int j = v[i-1].second + 1; j < v[i].first; ++j) s[j] = '0';
for(int j = v[i].first; j <= v[i].second; ++j) s[j] = '1';
}
}
if(v.size() > 1 )
{
int x = v.size();
if(v[x-1].first > v[x-2].second)
{
for(int i = v[x-2].second + 1; i < v[x-1].first; ++i) s[i] = '0';
for(int i = v[x-1].first; i <= v[x-1].second; ++i) s[i] = '1';
}
else
for(int i = v[x-2].second + 1; i <= v[x-1].second; ++i) s[i] = '1';
}
// 打个补丁
for(int i = 1; i < vv.size(); ++i)
{
if(vv[i-1].second + 1 > vv[i].first)
{
int x1 = (vv[i-1].first + vv[i-1].second) / 2;
int x2 = (vv[i].first + vv[i].second) / 2;
if((x1+x2) % 2 == 0) s[(x1+x2)/2] = '0';
}
}
printf("%s\n", s+1);
}
return 0;
}
B. Lord of the Values
两个操作:
1 a[i] = a[i] + a[j]
2 a[j] = a[j] - a[i]
显然是一道求通解的题目
我们设 a[i] = a, a[j] = b, i < j
初始: a b
选择:1 a+b b
2 a+b -a
1 b -a
2 b -a-b
1 -a -a-b
2 -a -b
经过6次变换即可让两个数变成相反数,
/**
* author: tourist
* created: 30.05.2021 17:40:11
**/
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
}
cout << 3 * n << '\n';
for (int i = 1; i <= n; i += 2)
{
cout << "1 " << i << " " << i + 1 << '\n';
cout << "2 " << i << " " << i + 1 << '\n';
cout << "1 " << i << " " << i + 1 << '\n';
cout << "2 " << i << " " << i + 1 << '\n';
cout << "1 " << i << " " << i + 1 << '\n';
cout << "2 " << i << " " << i + 1 << '\n';
}
}
return 0;
}
C. Compression and Expansion
模拟
主要是读懂怎么构造
#include<bits/stdc++.h>
using namespace std;
int ans[1009];
int t, n , x;
int main()
{
cin >> t;
while(t--)
{
memset(ans,0,sizeof(ans));
int cnt = 0;
cin >> n;
for(int i = 1; i <= n; ++i)
{
cin >> x;
if(x == 1) ans[++cnt] = x;
else
{
if(x == ans[cnt] + 1) ans[cnt] = x;
else
{
while(cnt && ans[cnt] != x-1) --cnt;
ans[cnt] = x;
}
}
for(int i = 1; i <= cnt; ++i)
cout << ans[i] << ".\n"[i==cnt];
}
cout << endl;
}
return 0;
}