第一题:相邻数对
解题思路:直接进行模拟即可。
以下是代码:
c++
#include<iostream>
using namespace std;
const int N = 1010;
int a[N] , n;
int main()
{
cin >> n;
for(int i = 0;i < n;i ++)
cin >> a[i];
long long res = 0;
for(int i = 0;i < n;i ++)
for(int j = i + 1;j < n;j ++)
if(abs(a[i] - a[j]) == 1) res ++;
cout << res << endl;
return 0;
}
python
n = int(input())
l = list(map(int , input().split()))
res = 0
for i in range(n):
for j in range(i + 1 , n):
if abs(l[i] - l[j]) == 1:
res += 1
print(res)
第二题:画图
解题思路:直接进行模拟即可。
以下是代码:
c++
#include<iostream>
#include<cstring>
using namespace std;
const int N = 110;
int t;
bool st[N][N];
int main()
{
memset(st , 0 , sizeof st);
cin >> t;
while(t --)
{
int a , b , c , d;
cin >> a >> b >> c >> d;
for(int i = a;i < c;i ++)
for(int j = b;j < d;j ++)
st[i][j] = true;
}
int res = 0;
for(int i = 0;i < N;i ++)
for(int j = 0;j < N;j ++)
if(st[i][j]) res ++;
cout << res << endl;
return 0;
}
python
st = [[False] * 105 for i in range(105)]
for _ in range(int(input())):
a , b , c , d = map(int , input().split())
for i in range(a , c):
for j in range(b , d):
st[i][j] = True
res = 0
for i in range(101):
for j in range(101):
if st[i][j]:
res += 1
print(res)
第三题:字符串匹配
解题思路:如果判断类型是0,那么统一将所有的大写字母改成小写字母,只需要枚举每一个字母,将大写字母使用异或32即可得到小写字母。
以下是代码:
c++
#include<iostream>
#include<algorithm>
using namespace std;
string s;
int type , t;
string change(string str)
{
string res;
for(char i : str)
if(i <= 'Z') res += i ^ 32;
else res += i;
return res;
}
int main()
{
cin >> s;
cin >> type;
if(!type) s = change(s);
cin >> t;
while(t --)
{
string str;
cin >> str;
if(!type && change(str).find(s) != -1) cout << str << endl;
else if(type && str.find(s) != -1) cout << str << endl;
}
return 0;
}
python
s = input()
t = int(input())
def change(s):
res = ''
for i in s:
if ord(i) <= ord('Z'):
res += chr(ord(i) + ord('a') - ord('A'))
else:
res += i
return res
if t == 0:
s = change(s)
for _ in range(int(input())):
w = input()
if t == 0:
if s in change(w):
print(w)
else:
if s in w:
print(w)
第四题:最优配餐
解题思路:使用bfs进行洪泛操作,对于每一个可以送出外卖的点加入队列,然后求出每一个可以到达的点的最短距离,最终成本就是所有的需要被送餐的点乘以需要的餐品的总数求和,即可得到答案。
以下是代码:
c++
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 1010;
int n, m, k, d;
bool g[N][N];
int dist[N][N];
queue<PII> q;
struct Target
{
int x, y, c;
}tg[N * N];
void bfs()
{
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i ++ )
{
int x = t.x + dx[i], y = t.y + dy[i];
if (x < 1 || x > n || y < 1 || y > n || g[x][y]) continue;
if (dist[x][y] > dist[t.x][t.y] + 1)
{
dist[x][y] = dist[t.x][t.y] + 1;
q.push({x, y});
}
}
}
}
int main()
{
scanf("%d%d%d%d", &n, &m, &k, &d);
memset(dist, 0x3f, sizeof dist);
while (m -- )
{
int x, y;
scanf("%d%d", &x, &y);
dist[x][y] = 0;
q.push({x, y});
}
for (int i = 0; i < k; i ++ )
scanf("%d%d%d", &tg[i].x, &tg[i].y, &tg[i].c);
while (d -- )
{
int x, y;
scanf("%d%d", &x, &y);
g[x][y] = true;
}
bfs();
LL res = 0;
for (int i = 0; i < k; i ++ )
res += dist[tg[i].x][tg[i].y] * tg[i].c;
printf("%lld\n", res);
return 0;
}
python
太慢了没过,还是使用c++
第五题:拼图
解题思路:
前后挨着的两列摆放有对应关系,我们可以用二进制位表示同一列各位的填充状态:1填充,0未填充
f[i][j], i 表示列号,j表示当前列的填充状态,f[i][j]表示方案数
f[i][0] = f[i-1][0]*w[0][0] + f[i-1][1]*w[1][0] + f[i-1][2] * w[2][0] +...+ f[i-1][2^m - 1]*w[2^m -1][0]
w矩阵是记录状态转移方案的矩阵,w[k][b]表示由相邻两列i, i+1 ,列i状态k转换到列i+1状态b的排布方案数
F[i] = {f[i][0],f[i][1],...,f[i][2^m - 1]}
F[i+1] = {f[i+1][0],f[i+1][1],...,f[i+1][2^m - 1]}
f[i+1][0] = f[i][0]*w[0][0] + f[i][1] * w[1][0]+...+ f[i][2^m -1] * w[2^m -1][0]
f[i+1][1] = f[i][0]*w[0][1] + f[i][1] * w[1][1]+...+ f[i][2^m -1] * w[2^m -1][1]
...
f[i+1][2^m -1] = f[i][0]*w[0][2^m -1] + f[i][1] * w[1][2^m -1]+...+ f[i][2^m -1] * w[2^m -1][2^m -1]
--> F[i+1] = F[i] * w
--> F[n] = F[n-1]* w = F[n-2]*w*w = ... = F[0]*w^n
F[0]只有一个合法状态就是f[0][2^m - 1] = 1,即第0列全部排满只有一种方案,其余方案数均为0
(学习学习)
以下是代码:
c++
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 130, mod = 1e9+7;
typedef long long LL;
int w[N][N];
LL n;
int m;
void dfs(int x,int y,int u)
{
if(u == m) w[x][y]++; // 枚举完x列的各个位,对应的方案数+1
if(x >> u & 1) return dfs(x,y,u+1); // x列第u位是非空状态,直接在看下一位
else
{
if(u && !(y >> u & 1) && !(y >> u - 1 & 1)) // 摆法1:当y列的 第u 和 u - 1位为空
dfs(x, y + (1 << u ) + (1 << u - 1), u + 1);
if(u + 1 < m && !(y >> u & 1) && !(y >> u + 1 & 1)) //摆法2:当y列的第u 和 u+1 位为空
dfs(x, y + (1 << u ) + (1 << u + 1), u + 1);
if(u + 1 <m && !(x >> u + 1 & 1)) // 列x的第u+1位也为空
{
if(!(y << u + 1 & 1)) dfs(x, y + 1<<u+1, u + 2); //摆法3,y的第u+1位为空
if(!(y << u & 1)) dfs(x, y + 1 << u, u + 2); //摆法4,y的第u位为空
}
}
}
void mulit(int c[][N], int a[][N],int b[][N])
{
static int tmp[N][N];
memset(tmp,0,sizeof tmp);
for(int i=0; i< 1<<m; i++)
for(int j = 0; j < 1<<m; j++)
for(int k = 0; k < 1<<m; k++)
tmp[i][j] = (tmp[i][j] + (LL)a[i][k] * b[k][j]) % mod; //矩阵乘法
memcpy(c,tmp,sizeof tmp);
}
int main()
{
cin >> n >> m;
for(int i=0; i< 1 <<m ; i++)
dfs(i,0,0);
int res[N][N] = {0}; //F
res[0][(1 << m )-1] = 1;
while(n)
{
if(n & 1) mulit(res,res,w);
mulit(w,w,w);
n >>= 1;
}
cout << res[0][(1 << m) - 1] << endl; //只有第一行是我们要的结果,所以是res[0],
return 0;
}