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;
}

浙公网安备 33010602011771号