acm专题六

一、第一题
代码:

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

思路:假设每次输入的数都是下一段的开头,如果此时和小于零,证明这段不符,从下一段开始,反之则可以继续延长这段

二、第二题
代码:

#include <bits/stdc++.h>
using namespace std;
int main() 
{
	int i,T,M,t[101],v[101],j,dp[1005]={0};
	cin>>T>>M;
	for(i=1;i<=M;i++) cin>>t[i]>>v[i];
	for(i=1;i<=M;i++)
	    for(int tt=T;tt>=t[i];tt--)
	        dp[tt]=max(dp[tt],dp[tt-t[i]]+v[i]);
	cout<<dp[T];
    return 0;
}

思路:遍历每种草药,倒着遍历足够时间,对取与不取两个情况判断

三、第三题
代码:

#include <bits/stdc++.h>
using namespace std;
int main() 
{
	int n,W,i,j,m=1,vv,ww,mm;
	cin>>n>>W;
	vector<int> v,w;
	for(i=0;i<n;i++)
	{
		cin>>vv>>ww>>mm;
		for(j=1;j<=mm;j<<=1) v.push_back(j*vv),w.push_back(j*ww),mm-=j;
		if(mm) v.push_back(mm*vv),w.push_back(mm*ww);
	} 
	vector<int> dp(W+1,0);
	for(i=0;i<v.size();i++)
	   for(int weight=W;weight>=w[i];weight--)
	       dp[weight]=max(dp[weight],dp[weight-w[i]]+v[i]);
	cout<<dp[W];
    return 0;
}

思路:将背包问题二进制优化

四、第四题
代码:

#include <bits/stdc++.h>
using namespace std;
int main() 
{
	int n,i,j,mapp[100001];
	cin>>n;
	vector<int> first(n),second(n),dp(n,100001);
	for(i=0;i<n;i++) cin>>first[i],mapp[first[i]]=i;
	for(i=0;i<n;i++) cin>>second[i],second[i]=mapp[second[i]];
	int ans=0,m=100001;
	for(i=0;i<n;i++) { auto it=upper_bound(dp.begin(),dp.end(),second[i]);*it=second[i];}
	for(i=0;i<n;i++)
	if(dp[i]!=100001) ++ans;
	else break;
	cout<<ans;
    return 0;
}

思路:用mapp数组将求解最大子序列转化为求解最大连续上升子序列

总结:dp关键在于状态转移方程和优化,so hard hard hard

posted @ 2025-02-16 15:17  astronomyy  阅读(7)  评论(0)    收藏  举报