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;
}
posted @ 2024-11-26 21:58  Kevinhwbb  阅读(15)  评论(0编辑  收藏  举报