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.

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

mod 109+7

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

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

n.len = n1.len+n1.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;
}

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

本文作者:liangqianxing

本文链接:https://www.cnblogs.com/liangqianxing/p/17048173.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   liangqianxing  阅读(274)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起