恭喜江莉ec final 夺冠
所以昨天高强度看榜 没有写题
dbq QAQ
AcWing 1022. 宠物小精灵之收服
二维费用背包
空间不够我们可以滚动数组优化 不过要反着跑
然后就是体力 j 不能为0 我可以将他看成一个j-1的背包就是了
反正不可以判断时加j>k这样会忽略从0开始的转化
最后自然check时 0 ~ v2-1
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
const int M = 5e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int V1,V2,f[N][N],n;
signed main(){
fast
cin>>V1>>V2>>n;
for(int i=1;i<=n;i++){
int v1,v2;cin>>v1>>v2;
for(int j=V1;j>=v1;j--)
for(int k=V2-1;k>=v2;k--)
f[j][k]=max(f[j][k],f[j-v1][k-v2]+1);
}
cout<<f[V1][V2-1]<<' ';
int j;
for(j=0;j<=V2-1;j++)if(f[V1][V2-1]==f[V1][j])break;
cout<<V2-j<<endl;
return ~~(0^_^0);
}
AcWing 278. 数字组合
呃呃 把f[i-1][j]和f[i-1][j-vi]弄一起了 卡了一会
实际上肯定时不行的
越学越回去了 属于是
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[N][M],n,m,a[N];
signed main(){
fast
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=0;i<=n;i++)f[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{f[i][j]=f[i-1][j];if(j>=a[i])f[i][j]+=f[i-1][j-a[i]];}
cout<<f[n][m]<<endl;
return ~~(0^_^0);
}
AcWing 1023. 买书
注意j枚举从0开始就是了 因为0的时候我们初始化没到 而把初始化提外面写是能写
要多几行
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[5][N],n,a[5]={0,10,20,50,100};
signed main(){
fast
cin>>n;
f[0][0]=1;
for(int i=1;i<=4;i++)
for(int j=0;j<=n;j++)
for(int k=0;k*a[i]<=j;k++)
f[i][j]+=f[i-1][j-k*a[i]];
cout<<f[4][n]<<endl;
return ~~(0^_^0);
}
AcWing 1021. 货币系统
#include <bits/stdc++.h>
using namespace std;
const int N = 3e3+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int n,m,f[20][N];
signed main(){
fast
cin>>n>>m;
int a[20];
for(int i=1;i<=n;i++)cin>>a[i];
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k*a[i]<=j;k++)
f[i][j]+=f[i-1][j-k*a[i]];
cout<<f[n][m]<<endl;
return ~~(0^_^0);
}
AcWing 532. 货币系统
我们不难看出这个题意是让大的数被小的数表示
最开始想的是填表法 多了一维 T了
后来想好像可以刷表 然后 就过了
我们把最开始存的表示成2 能换算过去变成1
我们只要碰到大于0的就刷一遍
不过只能刷比他小的面值把
这道题就结束咯~~~
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
signed main(){
fast
int t;cin>>t;
while(t--){
int f[25010]={0};
int a[N],n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],f[a[i]]=2;
sort(a+1,a+n+1);
int cnt=1;
for(int i=a[1];i<=a[n];i++){
if(f[i]>0){
for(int j=1;j<=cnt;j++){
if(a[j]+i<=a[n])f[a[j]+i]=1;
}
}
if(i==a[cnt])cnt++;
}
int ans=0;
for(int i=1;i<=n;i++)if(f[a[i]]==2)ans++;
cout<<ans<<endl;
}
return ~~(0^_^0);
}
AcWing 6. 多重背包问题 III
我超
好几把难
暴力我们都会
我看了这道题 他tag说要单调队列 可是我想了半天也没想出来那里可以单调队列
因为我们枚举每个K的时候就是O(1)的
然后退到j层 是根本和上一层无关的
呃呃
他居然是有个性质 我们%v后是小于v的 然后利用小的 递推过去
并且我们直接还有个(我们就用滚动数组来说啊
f[j]=max(f[j],f[j-v]+w,f[j-2v]+2w...,f[j-sv]+sw)
f[j-v]=max( f[j-v], f[j-2v]+w,....f[j-sv]+(s-1)w,f[j-(s+1)v]+sw)
f[j-2v]=...
f[j-3v]=...
这里也就是我们为什么不能用完全背包的来优化 因为完全背包是固定了s项 没有s+1项的
然后我们发现我们每个j-kv都是求前s个的max
这不就单调队列吗!
经过单调队列优化我们的时间复杂度O(nm)(因为可以把里面两层优化成线性
然后就是很重要的一点我们每次f[j-kv]后面加的w都是不同的
我们设余数为r
f[r]=max(f[r])
f[r+v]=max(f[r+v],f[r+v-v]+w)
f[r+2v]=max(f[r+2v],f[r+2v-v]+w,f[r+2v-2v]+2w)
我们把里面都减去合适kw
f[r]=max(f[r])
f[r+v]=max(f[r+v]-w,f[r])+w
f[r+2v]=max(f[r+2v]-2w,f[r+v]-w,f[r])+2w
当然我们入队比较的时候随便比比只要相对不变就是了
但是入队时应该严格的绝对值入队那就是当前的(k-dq.front)/v*w
当然你可以把这个max(f[r+2v]-2w,f[r+v]-w,f[r])拿去入队 当然出来的时候就要加上kw
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[N],backup[N];
signed main(){
fast
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++){
int v,w,s;cin>>v>>w>>s;
memcpy(backup,f,sizeof f);
for(int j=0;j<v;j++){
int dq[N];
int tt=-1,hh=0;
for(int k=j;k<=m;k+=v){
while(hh<=tt&&dq[hh]<k-s*v)hh++;
while(hh<=tt&&backup[dq[tt]]-(dq[tt]-j)/v*w<=backup[k]-(k-j)/v*w)tt--;
dq[++tt]=k;
if(hh<=tt)f[k]=max(f[k],backup[dq[hh]]+(k-dq[hh])/v*w);
}
}
}
cout<<f[m]<<endl;
return ~~(0^_^0);
}
AcWing 1019. 庆功会
一模一样 我甚至数据范围都没改
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[N],backup[N];
signed main(){
fast
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++){
int v,w,s;cin>>v>>w>>s;
memcpy(backup,f,sizeof f);
for(int j=0;j<v;j++){
int dq[N];
int tt=-1,hh=0;
for(int k=j;k<=m;k+=v){
while(hh<=tt&&dq[hh]<k-s*v)hh++;
while(hh<=tt&&backup[dq[tt]]-(dq[tt]-j)/v*w<=backup[k]-(k-j)/v*w)tt--;
dq[++tt]=k;
if(hh<=tt)f[k]=max(f[k],backup[dq[hh]]+(k-dq[hh])/v*w);
}
}
}
cout<<f[m]<<endl;
return ~~(0^_^0);
}
ACWing 7. 混合背包问题
处理一下输入就是了
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[N],backup[N];
signed main(){
fast
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++){
int v,w,s;cin>>v>>w>>s;
if(s==0)s=2e9;
else if(s==-1)s=1;
memcpy(backup,f,sizeof f);
for(int j=0;j<v;j++){
int dq[N];
int tt=-1,hh=0;
for(int k=j;k<=m;k+=v){
while(hh<=tt&&dq[hh]<k-s*v)hh++;
while(hh<=tt&&backup[dq[tt]]-(dq[tt]-j)/v*w<=backup[k]-(k-j)/v*w)tt--;
dq[++tt]=k;
if(hh<=tt)f[k]=max(f[k],backup[dq[hh]]+(k-dq[hh])/v*w);
}
}
}
cout<<f[m]<<endl;
return ~~(0^_^0);
}
AcWing 8. 二维费用的背包问题
看错题了 这也能难度中等???
我说再加一维k都称不上把呃呃
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[N][N],n,V1,V2;
signed main(){
fast
cin>>n>>V1>>V2;
for(int i=1;i<=n;i++){
int w,v1,v2;cin>>v1>>v2>>w;
for(int i=V1;i>=1;i--)
for(int j=V2;j>=0;j--)
if(i>=v1&&j>=v2)f[i][j]=max(f[i][j],f[i-v1][j-v2]+w);
}
cout<<f[V1][V2]<<endl;
return ~~(0^_^0);
}
1020. 潜水员
暴力写挂了 这题数据真不水
大概是1600*1600*1000感觉可以卡着过的
这道题唯一区别就是状态计算吧
要是小于的话我们还是要算进去的吧
#include <bits/stdc++.h>
using namespace std;
const int N = 1610;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int f[N][N],n,V1,V2;
signed main(){
fast
cin>>V1>>V2>>n;
memset(f,0x3f3f,sizeof f);
f[0][0]=0;
for(int i=1;i<=n;i++) {
int v1, v2, w;
cin >> v1 >> v2 >> w;
for (int j = V1; j >= 0; j--)
for (int k = V2; k >= 0; k--)
f[j][k] = min(f[j][k], f[max(0, j - v1)][max(0, k - v2)] + w);
}
cout<<f[V1][V2]<<endl;
return ~~(0^_^0);
}