【已完结】【专题】寒假后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;
}
posted @ 2025-05-04 09:53  cruisexsy2011  阅读(16)  评论(0)    收藏  举报