2024.11.26
今日总结
上午打南外的比赛,只会做第一题的Dp第二题的数位Dp差一点就想出来了,第三题打暴力挂了,第四题不会,下午吃饭前改完了第二题,晚上做了今天没有写的二本的比赛的前两题
1:团子制作
这道题是Dp加搜索的结合,需要一边搜索,一边进行Dp转移,一定要处理好边界问题,转移时要注意是二维转移
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 3e3 + 10;
int n,m,ans;
int dp[N *2][5];
char c[N][N];
bool hang(int x,int y)
{
return x >= 2 && x <= n - 1 && c[x - 1][y] == 'R' && c[x][y] == 'G' && c[x + 1][y] == 'W';
}
bool lie(int x,int y)
{
return y >= 2 && y <= m - 1 && c[x][y - 1] == 'R' && c[x][y] == 'G' && c[x][y + 1] == 'W';
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++)
cin >> c[i][j];
for(int i = 2;i <= n;i ++)
{
for(int j = 0;j <= max(n,m);j ++)
dp[j][0] = dp[j][1] = dp[j][2] = dp[j][3] = 0;
int u = 0,x = i,y = m;
while(x >= 1 && x <= n && y >= 1 && y <= m)
{
u ++;
dp[u][0] = max(dp[u - 1][0],max(dp[u - 1][1],max(dp[u - 1][2],dp[u - 1][3])));
dp[u][1] = max(dp[u - 1][0],dp[u - 1][1]) + lie(x,y);
dp[u][2] = max(dp[u - 1][0],dp[u - 1][2]) +hang(x,y);
x ++,y --;
}
ans += max(dp[u][0],max(dp[u][1],max(dp[u][2],dp[u][3])));
}
for(int i = 1;i <= m;i ++)
{
for(int j = 0;j <= max(n,m);j ++)
dp[j][0] = dp[j][1] = dp[j][2] = dp[j][3] = 0;
int u = 0,x = 1,y = i;
while(x >= 1 && x <= n && y >= 1 && y <= m)
{
u ++;
dp[u][0] = max(dp[u - 1][0],max(dp[u - 1][1],max(dp[u - 1][2],dp[u - 1][3])));
dp[u][1] = max(dp[u - 1][0],dp[u - 1][1]) + lie(x,y);
dp[u][2] = max(dp[u - 1][0],dp[u - 1][2]) + hang(x,y);
x ++,y --;
}
ans += max(dp[u][0],max(dp[u][1],max(dp[u][2],dp[u][3])));
}
printf("%d\n",ans);
return 0;
}
2:JinTianHao 和二叉树迷宫
这道题是一个比较神奇的数位Dp,这道题很容易判断错是向左还是向右,一定要注意!!!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
const int Mod = 1e9 + 7;
#define add(x,y) x = (x + y) % Mod
int n,k,ans;
int dp[N][N][2][2][2],g[N][N][2][2][2];
char s[N],l[N],r[N];
int main()
{
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k;
cin >> s >> l >> r;
dp[0][0][1][1][1] = g[0][0][1][1][1] = 1;
for(int i = 0;i < n;i ++)
{
for(int j = 0;j <= k;j ++)
{
for(int a = 0;a <= 1;a ++)
{
for(int b = 0;b <= 1;b ++)
{
for(int c = 0;c <= 1;c ++)
{
if(dp[i][j][a][b][c])
{
if(!a || l[i + 1] == '0') add(g[i + 1][j + (i && c != (s[i] == 'L'))][a][b && r[i + 1] == '0'][s[i] == 'L'], g[i][j][a][b][c]),add(dp[i + 1][j + (i && c != (s[i] == 'L'))][a][b && r[i + 1] == '0'][s[i] == 'L'], dp[i][j][a][b][c] * 2 % Mod);
if(!b || r[i + 1] == '1') add(g[i + 1][j + (i && c != (s[i] == 'R'))][a && l[i + 1] == '1'][b][s[i] == 'R'], g[i][j][a][b][c]),add(dp[i + 1][j + (i && c != (s[i] == 'R'))][a && l[i + 1] == '1'][b][s[i] == 'R'], dp[i][j][a][b][c] * 2ll + g[i][j][a][b][c]);
}
}
}
}
}
}
for(int j = k - 1;j <= k;j ++)
for(int a = 0;a <= 1;a ++)
for(int b = 0;b <= 1;b ++)
for(int c = 0;c <= 1;c ++)
add(ans,dp[n - 1][j][a][b][c]);
cout << ans << endl;
return 0;
}
3:难
这道题是一道贪心题,但是需要用带全排列的情况,用类似的减法原理,来解决
点击查看代码
//字符串哈希
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
int ans;
int s[N];
string a,b;
signed main()
{
cin >> a >> b;
int lena = a.length(),lenb = b.length();
for(int i = 0;i < lenb;i ++)
s[b[i] - 'a'] ++;
ans = (lena + 1) * (lenb + 1);
for(int i = 0;i < lena;i ++)
ans -= s[a[i] - 'a'];
printf("%lld\n",ans);
return 0;
}
4:点
这道题是一道树形Dp加上贪心加上数学的题目,这里的主要难点是对中位数的解读,如果这个解决了,剩下的动态转移方程很好想出
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int read()
{
int x = 0, w = 1;
char ch = 0;
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ '0');
ch = getchar();
}
return x * w;
}
void write(int x)
{
if (x < 0)
{
x = -x;
putchar('-');
}
if (x > 9)
write(x / 10);
putchar(x % 10 ^ '0');
}
const int N = 5e5 + 5, inf = 1e18;
int n, m;
int w[N];
int h[N], tot;
int d[N];
int res;
int mx[N];
int f[N][2];
struct edge
{
int to, nxt;
} e[N << 1];
void add(int u, int v)
{
e[++tot] = (edge){v, h[u]};
h[u] = tot;
}
void dfs(int u, int fa)
{
if (d[u] == 1 && u != 1)
return f[u][1] = -inf, void();
priority_queue<int> q;
int res = 0, t = 0, p = 0;
for (int i = h[u]; i; i = e[i].nxt)
{
int j = e[i].to;
if (j == fa)
continue;
dfs(j, u);
t = max(f[j][1] + w[u], f[j][0] + min(w[u], w[j]));
p = max(f[j][1] + m, f[j][0] + w[j]);
res += p;
q.push(t - p);
}
for (int i = 1; i < mx[u]; i++)
{
int tt = q.top();
q.pop();
res += tt;
}
f[u][0] = res;
f[u][1] = res + (q.size() ? q.top() : -inf);
}
signed main()
{
n = read(), m = read();
for (int i = 1; i <= n; i++)
w[i] = read();
for (int i = 1; i < n; i++)
{
int u = read(), v = read();
add(u, v), add(v, u);
d[u]++, d[v]++;
}
for (int i = 1; i <= n; i++)
mx[i] = d[i] / 2 + 1;
dfs(1, 0);
write(f[1][1]), puts("");
return 0;
}