acm寒假集训第六讲总结

1.最大子段和

思路:
遍历数组,每一步都有两种情况,继续累加或者开始一个新的子段,依靠做出选择后的结果哪个更大来判断,另外使用一个变量记录最大的子段和即可

代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n,i;
	cin>>n;
	int a[n];
	for(i=0;i<n;i++)
	{
		cin>>a[i];
	}
	int sum=a[0],sum_all=a[0];
	for(i=1;i<n;i++)
	{
		if(a[i]+sum>a[i])
		{
			sum+=a[i];
			if(sum>sum_all)
			{
				sum_all=sum;
			}
		}
		else
		{
			sum=a[i];
			if(sum>sum_all)
			{
				sum_all=sum;
			}
		}
	}
	cout<<sum_all;
} 

2.采药

思路:
使用0-1背包的模型,转移方程为f[j]=max(f[j],f[j-h[i].time]+h[i].value),即每种草药要么装入要么不装

代码:

#include <bits/stdc++.h>
using namespace std;
struct herb
{
	int time,value;
};
int main()
{
	int t,m;
	cin>>t>>m;
	int i,j;
	vector<struct herb> h;
	for(i=0;i<m;i++)
	{
		struct herb h1;
		cin>>h1.time>>h1.value;
		h.push_back(h1);
	}
	vector<int> f(t+5,0);
	for(i=0;i<m;i++)
	{
		for(j=t;j>=h[i].time;j--)
		{
			f[j]=max(f[j],f[j-h[i].time]+h[i].value);
		}
	}
	cout<<f[t];
	return 0;
} 

3.宝物筛选

思路:
使用多重背包的思路,为了保证不会TLE,使用二进制优化降低时间复杂度
代码:

#include <bits/stdc++.h>
using namespace std;

struct treasure 
{
    long long int weight, value, number;
};

int main() 
{
    long long int n, w;
    cin >> n >> w;
    vector<struct treasure> t;
    for (long long int i = 0; i < n; i++) 
	{
        struct treasure t1;
        cin >> t1.value >> t1.weight >> t1.number;
        t.push_back(t1);
    }

    vector<long long int> f(w + 1, 0);

    for (long long int i = 0; i < n; i++) 
	{
        long long int value = t[i].value, weight = t[i].weight, number = t[i].number;
        for (long long int k = 1; k <= number; k *= 2) 
		{
            number -= k;
            for (long long int j = w; j >= weight * k; j--) 
			{
                f[j] = max(f[j], f[j - weight * k] + value * k);
            }
        }
        if (number > 0) 
		{
            for (long long int j = w; j >= weight * number; j--) 
			{
                f[j] = max(f[j], f[j - weight * number] + value * number);
            }
        }
    }
    cout << f[w];
    return 0;
}

4.最长公共子序列

思路:
通过将最长公共子序列问题最长递增子序列问题降低时间复杂度,防止TLE
代码:

#include <bits/stdc++.h>
using namespace std;
int main() 
{
    int n;
    cin >> n;
    vector<int> p1(n + 1), p2(n + 1);
    for (int i = 1; i <= n; i++) cin >> p1[i];
    for (int i = 1; i <= n; i++) cin >> p2[i];
    vector<int> pos(n + 1, 0);
    for (int i = 1; i <= n; i++) 
	{
        pos[p2[i]] = i;
    }
    vector<int> seq;
    for (int i = 1; i <= n; i++) 
	{
        int val = pos[p1[i]];  
        if (val == 0) continue; 
        auto it = lower_bound(seq.begin(), seq.end(), val);
        if (it == seq.end()) 
		{
            seq.push_back(val); 
        } 
		else 
		{
            *it = val;
        }
    }
    cout << seq.size();
    return 0;
}

学习总结:
通过这次的学习,我学习了动态规划的相关知识,通过列出转移方程解决问题,主要学习了背包问题,包括0-1背包和多重背包,还了解到可以通过滚动数组避免MLE和使用二进制优化避免TLE的方法

posted @ 2025-02-16 22:55  asdadsdf  阅读(26)  评论(0)    收藏  举报