acwing过过一遍,不用就会淡忘,好消息是再看一眼就能想起来了😇

lc1908
nim游戏:把所有堆的数量异或,结果非零则当前玩家能赢
非零先手玩家只用将其变为0,然后镜像后手玩家操作,后手必败
class Solution {
public:
bool nimGame(vector<int>& piles) {
int t = 0;
for(int p : piles){
t ^= p;
}
++return t != 0;++
}
};
下面三题都是
枚举出规则 + dp/memo统计的思路
lc1931
三进制数表示m列网格的单行合法涂色方案,筛选出相邻列颜色不同的方案
memo统计n行相邻行同列颜色不同的总合法涂色数
class Solution {
public:
int f[1005][255];
int mod = 1e9 + 7, M;
bool check(int S) {
int last = -1;
for(int i = 0; i < M; ++i){
if(S%3==last)return false;
last = S%3;
S /= 3;
}
return true;
}
bool check_n(int x, int y) {
for(int i = 0; i < M; ++i) {
if(x%3==y%3)return false;
x/=3,y/=3;
}
return true;
}
int colorTheGrid(int m, int n) {
M = m;
int tot = 1;
for(int i = 1; i <= m; ++i)tot*=3;
for(int i = 0; i < tot; ++i)
if(check(i))f[1][i] = 1;
for(int i = 2; i <= n; ++i)
for(int j = 0; j < tot; ++j)
if(check(j))
for(int k = 0;k < tot; ++k)
if(check(k)) {
if(!check_n(j,k))continue;
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
int ans = 0;
for(int i = 0; i < tot; ++i)
ans = (ans + f[n][i]) % mod;
return ans;
}
};
lc2184
++dfs构造+check+dp memo计算++
DFS枚举所有单行长宽符合要求的砌砖间隙排列
dp统计高度达标且++相邻行间隙不重合++的合法砌墙方案总数
class Solution {
typedef long long ll;
const int mod=1e9+7;
public:
vector<vector<int>> vec;//所有排列
bool check(int i, int j){
// 判断第i种排列与第j种排列 能否相邻
auto& v1 = vec[i];
auto& v2 = vec[j];
int x = 1, y = 1;
while(x < v1.size() - 1 && y < v2.size() - 1){
if(v1[x] == v2[y]) return false;
if(v1[x] < v2[y]) x++;
else y++;
}
return true;
}
int buildWall(int height, int width, vector<int>& bricks) {
++vector<int> cur{0};//back init++
int n=bricks.size();
auto dfs=[&](this auto&& dfs,int need)
{
if(need == 0){
vec.push_back(cur);
return;
}
for(int i = 0; i < n; ++i)
{
if(need >= bricks[i]){
cur.push_back(++cur.back()+bricks[i]);++
++dfs(need - bricks[i]++ );
cur.pop_back();
}
}
};
dfs(width); //排列保存间隙的横坐标位置
int m = vec.size();
vector<vector<ll>> dp(height, vector<ll>(m, 0));
//dp 行排列组合种数
vector<vector<int>> last(m); //能与第i种排列 相邻的排列
for(int i = 0; i < m; ++i){
if(check(i,i))
++last[i].push_back(i);
//单块砖排列可重复用++
for(int j = i + 1; j < m; ++j){
if(check(i, j)){
last[i].push_back(j);
last[j].push_back(i);
}
}
}
for(int i = 0; i < m; ++i)
dp[0][i] = 1; // init
for(int i = 1; i < height; ++i){
for(int j = 0; j < m; ++j){
for(int k: last[j]){
++dp[i][j] += dp[i - 1][k++ ];
}
dp[i][j] %= mod;
}
}
ll ret = 0;
for(auto ev: dp.back()) ret += ev;
ret %= mod;
return (int)ret;
}
};