2024.11.9

今天上午打了梦熊oi的NOIP模拟赛
下午做了洛谷的题
1:https://www.luogu.com.cn/problem/P1541
这道题主要考察暴力DP的题目对限定的四种操作暴力循环DP列公式求解即可

点击查看代码
#include<bits/stdc++.h>

using namespace std;

const int N = 45;
const int M = 360;

int n,m;
int dp[N][N][N][N],num[M],g[5];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i ++)
        scanf("%d",&num[i]);
    dp[0][0][0][0] = num[1];
    for(int i = 1;i <= m;i ++)
    {
        int x;
        scanf("%d",&x);
        g[x] ++;
    }//每张牌的数量
    for(int a = 0;a <= g[1];a ++)
    {
        for(int b = 0;b <= g[2];b ++)
        {
            for(int c = 0;c <= g[3];c ++)
            {
                for(int d = 0;d <= g[4];d ++)
                {
                    int id = 1 +    a + 2 * b + 3 * c + 4 * d;
                    if(a != 0) dp[a][b][c][d] = max(dp[a][b][c][d],dp[a - 1][b][c][d] + num[id]);
                    if(b != 0) dp[a][b][c][d] = max(dp[a][b][c][d],dp[a][b - 1][c][d] + num[id]);
                    if(c != 0) dp[a][b][c][d] = max(dp[a][b][c][d],dp[a][b][c - 1][d] + num[id]);
                    if(d != 0) dp[a][b][c][d] = max(dp[a][b][c][d],dp[a][b][c][d - 1] + num[id]); 
                }
            }
        }
    }
    printf("%d\n",dp[g[1]][g[2]][g[3]][g[4]]);
    return 0;
}

2:https://www.luogu.com.cn/problem/P3558
这道题主要是考察对区间DP的练习,一定要注意判负,否则会CE,关于动态转移方程不好写,他需要对每一位进行转移

点击查看代码
#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;

int n;
int a[N],dp[N][3];

int main()
{
    scanf("%d",&n);
    memset(dp,0x3f,sizeof(dp));
    for(int i = 1;i <= n;i ++)
        scanf("%d",&a[i]);
    dp[1][a[1] + 1] = 0;    
    for(int i = 2;i <= n;i ++)
    {
        if(a[i] == 0) 
        {
            dp[i][0] = dp[i - 1][0] + 1;
            dp[i][1] = min(dp[i - 1][0],dp[i - 1][1]);
            dp[i][2] = dp[i - 1][2] + 1;
        }
        else if(a[i] == 1)
        {
            dp[i][0] = dp[i - 1][0] + 2;
            dp[i][1] = dp[i - 1][0] + 1;
            dp[i][2] = min(min(dp[i - 1][0],dp[i - 1][1]),dp[i - 1][2]);
        }
        else 
        {
            dp[i][0] = dp[i - 1][0];
            dp[i][2] = dp[i - 1][2] + 2;
        }
    }
    int ans = min(min(dp[n][0],dp[n][1]),dp[n][2]);
    if(ans < INF) printf("%d\n",ans);
    else puts("BRAK");
    return 0;
}

3:https://www.luogu.com.cn/problem/P1156
这道主要考察的是01背包问题,这道题需要特殊考虑两种同态合并的优化方式

点击查看代码
# include<iostream>
# include<cstring>
# include<algorithm>
using namespace std;
struct p{
    int t,h,l;
}c[101];
int d,g;
int ti[101];
int f[101];
bool cmp(p a,p b)
{
    return a.t<b.t;
}
int main()
{
    cin>>d>>g;
    for(int i=1;i<=g;i++)
      cin>>c[i].t>>c[i].l>>c[i].h;
    sort(c+1,c+1+g,cmp);
    f[0]=10;
    for(int i=1;i<=g;i++)
      for(int j=d;j>=0;j--)
        if(f[j]>=c[i].t)
        {
            if(j+c[i].h>=d)
            {
                cout<<c[i].t;
                return 0;
            }
            f[j+c[i].h]=max(f[j+c[i].h],f[j]);
            f[j]+=c[i].l;
        }
    cout<<f[0];
    return 0;
}

4:https://www.luogu.com.cn/problem/P4158
这道题主要考察的是DP的优化,他需要列两个不同状态的动态转移方程

点击查看代码
#include<bits/stdc++.h>

using namespace std;

const int N = 2510;

int n,m,tim;
int colour[N],dp[N][N][2],ans[N];


int main()
{
	scanf("%d%d%d",&n,&m,&tim);
	for(int pop = 1;pop <= n;pop ++)
	{
		for(int i = 1;i <= m;i ++)
			scanf("%1d",&colour[i]);
		memset(dp,0,sizeof(0));
		for(int i = 1;i <= m;i ++)
		{
			for(int j = 1;j <= i;j ++)
			{
				dp[i][j][colour[i]] = dp[i - 1][j][colour[i]] + 1;
				dp[i][j][!colour[i]] = dp[i - 1][j][!colour[i]];
				int Max = max(dp[i - 1][j - 1][0],dp[i - 1][j - 1][1]);
				dp[i][j][colour[i]] = max(dp[i][j][colour[i]],Max + 1);
				dp[i][j][!colour[i]] = max(dp[i][j][!colour[i]],Max);
			}
		}
		for(int i = tim;i >= 1;i --)
		{
			for(int j = 0;j <= min(m,i);j ++)
			{
				ans[i] = max(ans[i],ans[i - j] + max(dp[m][j][0],dp[m][j][1]));
			}
		}
	}
	printf("%d\n",ans[tim]);
	return 0;
}

5:https://www.luogu.com.cn/problem/P2827
这道题看题目可以看出具备堆的性质,但数据较多,应用优先队列优化

点击查看代码
#include<bits/stdc++.h>

using namespace std;

#define int long long 

const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;

int n,m,q,u,v,t,x,y;
int nxt[N];
queue<int> a,b,c;

bool cmp(int x,int y)
{
    return x > y;
}

signed main()
{
    cin >> n >> m >> q >> u >> v >> t;
    for(int i = 1;i <= n;i ++)
        cin >> nxt[i];
    sort(nxt + 1,nxt + 1 + n,cmp);
    for(int i = 1;i <= n;i ++)
        a.push(nxt[i]);
    for(int i = 1;i <= m;i ++)
    {
        int Max = -INF,f;
        if(!a.empty()) if(a.front() > Max) Max = a.front(),f = 1;
        if(!b.empty()) if(b.front() > Max) Max = b.front(),f = 2;
        if(!c.empty()) if(c.front() > Max) Max = c.front(),f = 3;
        if(f == 1) a.pop();
        else if(f == 2) b.pop();
        else if(f == 3) c.pop();
        Max += (i - 1) * q;
        x = Max * u / v;
        y = Max - x;
        if(!(i % t)) cout << Max << " ";
        b.push(x - i * q);
        c.push(y - i * q);
    }
    cout << endl;
    int p = 1;
    while(p)
    {
        int Max = -INF,f;
        if(a.empty() && b.empty() && c.empty()) break;
        if(!a.empty()) if(a.front() > Max) Max = a.front(),f = 1;
        if(!b.empty()) if(b.front() > Max) Max = b.front(),f = 2;
        if(!c.empty()) if(c.front() > Max) Max = c.front(),f = 3;
        if(f == 1) a.pop();
        if(f == 2) b.pop();
        if(f == 3) c.pop();
        if(p % t == 0) cout << Max + m * q << " ";
        p ++;
    }
    cout << endl;
    return 0;
}
posted @ 2024-11-09 21:27  Kevinhwbb  阅读(18)  评论(0)    收藏  举报