【已完结】【专题】寒假后DP1
复习一遍发现好多都是可以压维的(
填数字
直接dp,遇到数字直接加,遇到问号 \(0 \sim 9\) 枚举即可。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=1e5+10;
#define int ll
char c[N];
mint f[N][20];
void MAIN(){
cin>>(c+1);
int n=strlen(c+1);
// For(i,1,n)f[i][0]=f[0][i]=1;
f[0][0]=1;
For(i,1,n){
For(j,0,12){
if(c[i]>='0'&&c[i]<='9'){
int x=c[i]-'0';
f[i][(j*10+x)%13]+=f[i-1][j];
}
else{
For(x,0,9){
f[i][(j*10+x)%13]+=f[i-1][j];
}
}
}
}
cout<<f[n][5].x<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
连胜奖(ABC261D)
用 \(f_{i,j,0/1}\) 表示抛了 \(i\) 次硬币 ,计数器的示数为 \(j\) (即连续 \(j\) 次为正面),上一次硬币为正/反面(1表示正面,0表示反面)。
\[f_{i,j,k}=
\begin{cases}
f_{i-1,j-1,k}+X_{i}+Y_{j}\space\space\space\space \left( k\ne0 \right)\\
f_{i-1,l,0}\space\space\space\space \left( k=0 ,0\leq l\leq i\right)
\end{cases}
\]
当然了,把第三维压了也可以。
时间复杂度 \(O(n^2)\)
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=998244353;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
#define int ll
const int N=5010;
int n,m,ans=0;
int a[N],y[N],f[N][N][2];
void MAIN(){
cin>>n>>m;
For(i,1,n) cin>>a[i];
For(i,1,m,c){
cin>>c;
cin>>y[c];
}
For(i,1,n){
For(j,2,i){
f[i][j][1]=max(f[i-1][j-1][1]+a[i]+y[j],f[i][j][1]);
// cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
}
f[i][1][1]=max(f[i][1][1],f[i-1][0][0]+a[i]+y[1]);
Rep(j,1,i){
f[i][0][0]=max(f[i][0][0],f[i-1][j][1]);
}
f[i][0][0]=max(f[i][0][0],f[i-1][0][0]);
}
For(i,0,n) ans=max(ans,f[n][i][1]);
ans=max(ans,f[n][0][0]);
cout<<ans<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
开箱子(ABC142E)
状压dp。
设 \(f_{S}\) 表示开启集合 \(S\) 所需的最小花费。
时间复杂度 \(O(m2^n)\)
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=20,M=1e3+10;
#define int ll
int n,m,ans=1e9,tot;
int a[M],b[M],c[M][N],cu[N],s[M],f[5 * M];
void MAIN(){
cin>>n>>m;
For(i,1,m){
cin>>a[i]>>b[i];
For(j,1,b[i]) cin>>c[i][j],s[i]+=(1<<c[i][j]-1);
}
me(f,0x3f);
f[0]=0;//初始化
Rep(i,0,m){
Rep(j,0,1<<n){
f[j|s[i+1]]=min(f[j]+a[i+1],f[j|s[i+1]]);//转移方程
}
}
cout<<(f[(1<<n)-1]==0x3f3f3f3f3f3f3f3f?-1:f[(1<<n)-1])<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
吃大餐(ABC142E)
F1:转换题目,在整个过程中只能使用一次魔法,使得某一道菜编程1的时间吃完。
时间复杂度 \(O(nt)\)
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=3e3+10;
#define int ll
struct no{
int a,b;
void rd(){cin>>a>>b;}
}v[N];
int f[N][N][2];
int n,t;
void MAIN(){
cin>>n>>t;
For(i,1,n) v[i].rd();
For(i,1,n){
For(j,0,t){
f[i][j][0]=f[i-1][j][0],f[i][j][1]=f[i-1][j][1];
if(j>=v[i].a){
f[i][j][0]=max(f[i][j][0],f[i-1][j-v[i].a][0]+v[i].b);
f[i][j][1]=max(f[i][j][1],f[i-1][j-v[i].a][1]+v[i].b);
}
if(j>=1){
f[i][j][1]=max(f[i][j][1],f[i-1][j-1][0]+v[i].b);
}
}
}
cout<<f[n][t][1]<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
F2:用 \(f\) 表示前 \(i\) 道菜吃 \(j\) 的时间获得的价值,
用 \(g\) 表示后 \(i\) 道菜吃 \(k\) 的时间获得的价值。答案是 \(max(f[i-1][j] + g[i+1][T-1-j] + a[i].v)\)。
时间复杂度 \(O(nt)\)
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=3e3+10;
#define int ll
struct no{
int a,b;
void rd(){cin>>a>>b;}
}v[N];
int f[N][N],g[N][N];
int n,t;
void MAIN(){
cin>>n>>t;
For(i,1,n) v[i].rd();
f[0][0]=g[n+1][0]=0;
For(i,1,n){
For(j,0,t){
f[i][j]=f[i-1][j];
if(j>=v[i].a){
f[i][j]=max(f[i][j],f[i-1][j-v[i].a]+v[i].b);
}
}
}
foR(i,n,1){
For(j,0,t){
g[i][j]=g[i+1][j];
if(j>=v[i].a){
g[i][j]=max(g[i][j],g[i+1][j-v[i].a]+v[i].b);
}
}
}
int ans=0;
For(i,1,n)Rep(j,0,t){
ans=max(ans,f[i-1][j]+g[i+1][t-1-j]+v[i].b);
}
cout<<ans<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
F3:考虑贪心,依然考虑哪个菜是最后一道,对应背包总容量发生变化。贪心策略:可以选择的菜越多对应的背包总容量尽可能大。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=6e3+10;
#define int ll
struct no{
int a,b;
void rd(){cin>>a>>b;}
}v[N];
int f[N];
int n,t;
void MAIN(){
cin>>n>>t;
For(i,1,n) v[i].rd();
sort(v+1,v+n+1,[](no x,no y){return x.a<y.a;});
me(f,0);
For(i,1,n){
foR(j,t+v[i].a-1,v[i].a){
f[j]=max(f[j],f[j-v[i].a]+v[i].b);
}
}
cout<<*max_element(f+1,f+N+1)<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
猫猫cpu的缓存
暴力:
若 \(p_{j}\sim p_{i}\)的距离大于或等于 \(k\) ,这个并集的大小就是 \(p_{j}-p_{i}+1\)。
否则,这个集合的大小是 \(k\)。
时间复杂度 \(O(m^2)\)
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=3e5+10;
int n,k,m;
int p[N],f[N];
void MAIN(){
cin>>n>>k>>m;
For(i,1,m) cin>>p[i];
sort(p+1,p+m+1);
me(f,0x3f);f[0]=0;
For(i,1,m){
For(j,0,i){
if(p[i]-p[j+1]+1>=k){
f[i]=min(f[i],f[j]+p[i]-p[j+1]+1);
}
else f[i]=min(f[i],f[j]+k);
}
}
cout<<f[m]<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
正解:
\(f_{i}=f_{j}+p_{i}-p_{j+1}+1\Rightarrow f_{i}=f_{j}-p_{j+1}+p_{i}+1\)
因为 \(p_{i}+1\) 是定值,因此取 \(f_{j}-p_{j+1}\) 的最小值即可,尺取即可。
时间复杂度 \(O(m)\)
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e9+7;
struct mint{
ll x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=3e5+10;
int n,k,m;
int p[N],f[N];
void MAIN(){
cin>>n>>k>>m;
For(i,1,m) cin>>p[i];
sort(p+1,p+m+1);
me(f,0x3f);f[0]=0;
int j=0,mn=1e9;
For(i,1,m){
while(p[i]-p[j+1]+1>k&&j<i){
mn=min(mn,f[j]-p[j+1]);
j++;
}
f[i]=min(mn+p[i]+1,f[j]+k);
}
cout<<f[m]<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}

浙公网安备 33010602011771号