DP

DP是什么

就我而言,DP是需要做出最优选择的一种题目,而且是全局最优的选择

DP有个性质,是相关性,就后面做的决策可以在之前做的决策上进行

而且没有后效性

数组的下标代表状态,数组中数的值代表value


贴一个题

D - Snuke Panic (1D) (atcoder.jp)

这个题的状态转移方程是dp[x][t]=max(dp[x-1][t-1],dp[x][t-1],dp[x+1][t-1])+a[x]

key : fup(j,0,min(4ll,i)

这道题一个很关键的地方就是上面的key,如果j>i的话,那就是不可能走到的,由此获得的状态也是不可能的,会干扰后续的计算

const int N=2e5+10;
int n,m,k,x,y,z;
int f[N][10],s[N][10];
void solve(){
	//try it again.
	cin>>n;
	int maxt=0;
	up(1,n){
		cin>>x>>y>>z;
		s[x][y]=z;
		maxt=max(maxt,x);
	}
	f[0][0]=0;
	fup(i,1,maxt){
		fup(j,0,min(4ll,i)){
			if(j){
				f[i][j]=max(f[i-1][j],f[i-1][j-1]);
			}
			f[i][j]=max({f[i-1][j],f[i-1][j-1],f[i-1][j+1]});
			f[i][j]+=s[i][j];
		}
	}
	int ans=0;
	for(int i=0;i<=4ll;i++)
		ans=max(ans,f[maxt][i]);
	// debug(ans);
	cout<<ans;
}

今天补了一道Div2的C题,也是一道DP

C. The Sports Festival

这个题是用dfs来完成状态的转移的

int n,m,k,a[N],b[N],p[N];
int f[N][N];
void solve(){
	//try it again.
	cin>>n;
	up(1,n)cin>>a[o];
	sort(a+1,a+1+n);
	mem1(f);
	function<int(int,int)>dfs=[&](int l,int r){
		if(l==r)return f[l][r]=0;
		if(f[l][r]!=-1)return f[l][r];
		f[l][r]=min(dfs(l,r-1),dfs(l+1,r))+(a[r]-a[l]);
		return f[l][r];
	};
	dfs(1,n);
	puts(f[1][n]);
}

今天Acwing的周赛最后一题也是一个DP
可惜我当搜索写的,然后TLE了呜呜呜

4796. 删除序列

链接:4796. 删除序列 - AcWing题库

给定一个长度为 n 的正整数序列 a。

你可以进行任意次删除操作。

每次删除操作分为两步:

  1. 选择序列中的一个元素(不妨设其元素值为 x),并将这一个元素删除,这可以给你加 x 分。
  2. 所有元素值x-1x+1 的元素(如果有的话)从序列中删除,这不会给你带来任何分数。

请计算,通过删除操作,你可以获得的最大得分。

输入格式

第一行包含整数 n

第二行包含 n 个正整数 a[1],a[2],a[3].....a[n]

输出格式

一个整数,表示可以获得的最大得分。

数据范围

前 6个测试点满足 1<=n<=10
所有测试点满足 1 <=n <= 10^51 <= a[i] <= 10^5

输入样例1:

2
1 2

输出样例1:

2

输入样例2:

3
1 2 3

输出样例2:

4

输入样例3:

9
1 2 1 3 2 2 2 2 3

输出样例3:

10

我们可以发现每一个点能不能选只与前一个点的状态有关

if(前面的点选了) then 这个点不能选

if(前面的点没有选) then 这个点可以选也可以不选

由此我们可以推出方程f[i][0]=max(f[i-1][1],f[i-1][0]) f[i][1]=max(f[i][0],f[i-1][0]+cnt[i]*i)

正确代码:

int n,m,k,a[N],b[N],p[N];
int f[N][2];
void solve(){
	//try it again.
	cin>>n;
	up(1,n){
		int x;
		cin>>x;
		a[x]++;
	}
	fup(i,1,100000){
		f[i][0]=max(f[i-1][0],f[i-1][1]);
		f[i][1]=f[i-1][0]+a[i]*i;
	}
	puts(max(f[100000][0],f[100000][1]));
}

因为本人是小白所以想的搜索TLE15了哈哈哈

我滴TLE代码:

const int N=100005;
int n,m,k,a[100005],b[N],p[N];
bool stt[100050];
int mp[100050];
map<PII,bool>st;
void solve(){
	//try it again.
	cin>>n;
	up(1,n)cin>>a[o];
	mem0(mp);
	st.clear();
	mem0(stt);
	sort(a+1,a+1+n);
	up(1,n){
		stt[a[o]]=true;
		mp[a[o]]++;
	}
	int ans=0;
	int maxl=a[n];
	function<void(bool,int,int)>dfs=[&](bool state,int x,int carry){
		if(st[{state,x}]>carry)return;
		st[{state,x}]=carry;
		if(x==maxl+1){
			ans=max(ans,carry);
			return;
		}
		if(!stt[x]){dfs(false,x+1,carry);return;}
		if(state==true)dfs(false,x+1,carry);
		else dfs(true,x+1,carry+mp[x]*x),dfs(false,x+1,carry);
	};
	dfs(false,0,0);
	puts(ans);
}

其实本来一开始想写DP的QWQ,可惜脑子混了写了个DP[2][2][2][N]这样的鬼东西,于是乎死活没写出来

后来理清楚思路又转到搜索了,然后好不容易搜索的思路对了,于是就TLE了哈哈哈

就这样与第一次AK擦肩而过

不过学到了DP

依然是很开心啦!


1/15补了一道 预处理的DP题
补了一道预处理的DP

Problem - C - Codeforces

For the first test, \(1912\) becomes \(21023\) after \(1\) operation which is of length \(5\).

For the second test, \(5\) becomes \(21\) after \(6\) operations which is of length \(2\).

For the third test, \(999\) becomes \(101010\) after \(1\) operation which is of length \(6\).

For the fourth test, \(88\) becomes \(1010\) after \(2\) operations which is of length \(4\).

题目给出\(n\)\(m\),要求出 \(n\)经过\(m\)次操作以后的长度

\(mod\) \(10^9+7\)

我们可以分析知道 给出的n当中每一个位置上都可以视为单独进行的操作

n与n-1之间也存在着联系

\(n.len\) \(=\) \(n-1.len + n-1.cnt[9]\)

由此便可以形成状态之间的关系

下面给出 key code

const int N=2e5+10;
const int mod=1e9+7;
int n,m,k,a[N],b[N],p[N];
struct point{
	int cnt[10];
	int len;
}dp[N];
void solve(){
	//try it again.
	cin>>n>>m;
	int ans=0;
	while(n){
		(ans+=dp[n%10+m].len)%=mod;
		n/=10;
	}
	puts(ans);
}
signed main(){
	IOS;
	dp[0].len=1;
	dp[0].cnt[0]=1;
	fup(o,1,N){
		(dp[o].len=dp[o-1].len+dp[o-1].cnt[9])%=mod;
		fup(j,1,9){
			(dp[o].cnt[j]+=dp[o-1].cnt[j-1])%=mod;
		}
		(dp[o].cnt[1]+=dp[o-1].cnt[9])%=mod;
		(dp[o].cnt[0]+=dp[o-1].cnt[9])%=mod;
	}
	int __;
	cin>>__;
	while(__--)
		solve();
    return 0;
}

这个题取模的方法很妙,偷了

posted @ 2023-01-12 22:36  liangqianxing  阅读(280)  评论(0)    收藏  举报