动态规划初步-结合牛客网第二场 D 以及 洛谷 P1020 (待补充)

牛客网的:

比赛的时候好不容易写出了转移方程,可能是因为一点步数的原因卡了很久,也把题目读了很多遍。

其实就是每个点都达到最优,然后我们的策略有,买或者不买。

emmm...  动态规划  在每个地方停下来都是最优的。

但是步数有点小问题,这个要想明白,我的代码:

#include<iostream>
#include<algorithm>
#include<string>
#include<set>
using namespace std;
typedef long long ll;
ll a[100005];
ll dp[3][100005];
ll s[3][100005];
int main() {
ll t; cin >> t; while (t--) {
ll n; cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];


//不买的话,可能不卖,或者是把上一个给卖了
dp[0][1] = 0; s[0][1] = 0;
dp[1][1] = -a[1]; s[1][1] = 1;//买了的

//dp[2][1] = 0;
for (int i = 2; i <= n; i++) {
//if (a[i] == 0) {
//	dp[0][i] = dp[0][i - 1];
//	dp[1][i] = dp[1][i - 1];
//	s[1][i] = s[1][i - 1];
//	s[0][i] = s[0][i - 1];
//	continue;
//}
dp[0][i] = max(dp[0][i - 1], dp[1][i - 1] + a[i]);// , dp[2][i - 1]);
dp[1][i] = max(dp[0][i - 1] - a[i], dp[1][i - 1]);
//dp[2][i] = dp[1][i - 1] + a[i];
//卖了的话
//cout << "没买"<<dp[0][i] << endl;
//cout <<"买了"<< dp[1][i] << endl;
//cout << "卖了" << dp[2][i] << endl;
if (max(dp[0][i - 1], dp[1][i - 1] + a[i]) == dp[0][i - 1]) {
s[0][i] = s[0][i - 1];//没买  就是上个没买
}
else if (max(dp[0][i - 1], dp[1][i - 1] + a[i]) == dp[1][i - 1] + a[i]) {
s[0][i] = s[1][i - 1] + 1;
}

if (max(dp[0][i - 1] - a[i], dp[1][i - 1]) == (dp[1][i - 1])) {
s[1][i] = s[1][i - 1];
}
else 	if (max(dp[0][i - 1] - a[i], dp[1][i - 1]) == (dp[0][i - 1] - a[i]))
{
s[1][i] = s[0][i - 1] + 1;
}

//cout <<" 没买" << s[0][i-1] << endl;
//cout << "买了"<<s[1][i - 1] << endl;
}

//s[1][i] = s[0][i - 1] + 1;//买了  就是以前的加一
//买了的话,可能..??

cout << dp[0][n] << " "<<s[0][n]<<endl;

}

return 0;
}

应该是这个吧...

反正最重要的是下面这两行

(因为想取最小的  所以+1放在后面 就这一点卡了10%的数据啊啊)

然后  ,有的人这么写 、

不知道谁的 截个图表示尊敬。。。  反正下面这样分类也可以啦

_(:з」∠)_  洛谷的界面也很舒服啊 但是一想到初中生高中生就有点不舒服。。。。

问题在哪里呢,其实上面那个题,只要看它是不是一直下降

一直上升着,上升着,下降了的时候就把它卖出去。这样就简单了呢

 

同样 洛谷这个导弹拦截系统  我就没用dp

其实它只是一个 最长上升子序列问题 就很简单了

但我想的   每个状态只能用一次  然后在任何一个状态停下来。

都能用吧 然后第二问还没A(待补充)

https://blog.csdn.net/fsahfgsadhsakndas/article/details/57918879

#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<cstdio>
using namespace std;
typedef long long ll;
struct node {
	int a;
	int s;
} node[100005];
int main() {
	int aa;
	int n = 0;
	int kk = 10;
	while (scanf("%d", &node[++n].a) != EOF)
		continue;
	//这里因为最后一行也++n了 只是没读到东西
	n--;
	node[0].a = 50005;
	node[0].s = 0;
	int record = 0;
	//其实我的strut 完全可以用两个数组代替..
	for (int i = 1; i <= n; i++) {
		record = 0;
		for (int j = 0; j < i; j++) {//  j是用于检验的,从前往后所有的..
			//	cout << node[j].a<<" " << node[i].a <<" "<< node[i].s <<" "<< node[j].s;
			if ((node[j].a >= node[i].a) && (node[j].s >= record)) {
				node[i].a = node[i].a;
				record = node[j].s;
			}
			node[i].s = record + 1;
		}
		//【果然对我而言这里非常容易错】
		//i j这里错的 ,然后要先看自己的程序再..
		//cout << i <<" "<< node[i].a <<" "<< node[i].s << endl;
	}
	int temp = 0;
	//这里其实可以直接优化的 ...
	for (int i = 1; i <= n; i++) {
		temp = max(temp, node[i].s);
	}
	cout << temp << endl;
	 int cnt;
	int maxx = 0;
	int ans = 0;
	int c[100005]; int j;
	for (int i = 1; i <= n; i++) {

		for ( j = 1; j <= ans; j++) {
			if (c[j] >= node[i].a) {
				//ans++;
				c[j] = node[i].a;
				break;
				//这里可以直接 用c[ans++]=node[i].a代替什么的
			}
			//我们要平等.. 怎么判断它开了
			//j是开了链子的数目啊啊啊啊....
			//如果找得到,只要能连就连上,因为其他的如果大于它,顺序在后面只能开新的
			//如果找不到,也只能开新的
			//..  顺序是多么重要啊
		}
		if(j>ans)
		{
			ans++;
			c[ans] = node[i].a;
		}
	}
	cout << ans << endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值