令人痛苦的三道题

#include<bits/stdc++.h>
using namespace std;
int n,a[2][2005],dp[2005][2][3005];
int read()
{
	char c;
	int x;
	for(c=getchar();c>'9'||c<'0';c=getchar());
	x=c-'0';
	for(c=getchar();c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
	return x;
}
int main()
{
	freopen("homework.in","r",stdin);
	freopen("homework.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++) 
	a[0][i]=read(),a[1][i]=read();
    memset(dp,0x3f,sizeof(dp));
    dp[1][0][0]=dp[1][1][0]=0;
    for(int i=1;i<=n;i++)
    for(int j=0;j<=1;j++)
    for(int k=0;k<=3000;k++)
    {
    	dp[i+1][j][max(k-a[j][i],0)]=min(dp[i+1][j][max(k-a[j][i],0)],dp[i][j][k]+a[j][i]);
    	dp[i+1][j^1][max(a[j][i]-k,0)]=min(dp[i+1][j^1][max(a[j][i]-k,0)],dp[i][j][k]+k);
    }
    int ans=0x7fffffff;
    for(int i=0;i<=3000;i++)
    for(int j=0;j<=1;j++)
    ans=min(ans,dp[n+1][j][i]);
    cout<<ans;
	return 0;
}
/*
3
1 3
1 3
1 3
*/

#include<bits/stdc++.h>
using namespace std;
const int mod=10007;
int f[50005][2],ans;
int n,m,a[50005],tot,all,length,maxa,l,r,sum[50005],que[50005];
long long read()
{
	char c;
	long long x;
	for(c=getchar();c>'9'||c<'0';c=getchar());
	x=c-'0';
	for(c=getchar();c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
	return x;
}
int main()
{
	freopen("cut.in","r",stdin);
	freopen("cut.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	a[i]=read(),tot+=a[i],maxa=max(maxa,a[i]);
	l=max(tot/(m+1),maxa);
	r=tot;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		int shu=0;
		all=0;
		for(int i=1;i<=n;i++)
		{
			if(shu+a[i]>mid)
			all++,shu=a[i];
			else shu+=a[i];
		}
		if(shu!=0) all++;
		if(l==r) break;
		if(all>m+1) l=mid+1;
		else r=mid;
	}
	length=l;
	for(int i=1;i<=n;i++)
	sum[i]=sum[i-1]+a[i];
	int now=0;
	for(int i=0;i<=m;i++)
	{
		int head=1,tail=1,value=0;
		for(int j=1;j<=n;j++)
		{
			if(i==0)
			{
				 if(sum[j]<=length) f[j][now]=1;
				 else f[j][now]=0;
			}
			else {
				while(head<tail&&sum[j]-sum[que[head]]>length)
				value=(value+mod-f[que[head]][now^1])%mod,head++;
				int k=que[head];
				f[j][now]=value;
			}
			que[++tail]=j;
			value=(value+f[j][now^1])%mod;
		}
		ans=(ans+f[n][now])%mod;
		now^=1;
	}
	cout<<length<<" "<<ans;
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
int lu[200005],n,pd[200005],to[800005],w[800005],next[800005];
int tot,head[200005];
long long read()
{
	char c;
	long long x;
	for(c=getchar();c>'9'||c<'0';c=getchar());
	x=c-'0';
	for(c=getchar();c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
	return x;
}
struct node
{
	long long x,y,num;
}a[200005];
void add(int x,int y,int z)
{
	to[++tot]=y;
	w[tot]=z;
	next[tot]=head[x];
	head[x]=tot;
}
bool cmp1(const node &a,const node &b)
{
	return a.x<b.x;
}
bool cmp2(const node &a,const node &b)
{
	return a.y<b.y;
}
void spfa()
{
	queue <int> que;
	que.push(1);
	memset(lu,127,sizeof(lu));
	lu[1]=0;
	pd[1]=1;
	while(!que.empty())
	{
		int x=que.front();
		que.pop();
		pd[x]=0;
		for(int i=head[x];i;i=next[i])
		{
			int y=to[i];
			if(lu[y]>lu[x]+w[i])
			{
				lu[y]=lu[x]+w[i];
				if(!pd[y])
				{
					que.push(y);
					pd[y]=1;
				}
			}
		}
	}
}
int main()
{
	freopen("run.in","r",stdin);
	freopen("run.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		a[i].x=read();
		a[i].y=read();
		a[i].num=i;
	}
	sort(a+1,a+n+1,cmp1);
	for(int i=1;i<=n-1;i++)
	{
		add(a[i].num,a[i+1].num,abs(a[i+1].x-a[i].x));
		add(a[i+1].num,a[i].num,abs(a[i+1].x-a[i].x));
	}
	sort(a+1,a+n+1,cmp2);
	for(int i=1;i<=n-1;i++)
	{
		add(a[i].num,a[i+1].num,abs(a[i+1].y-a[i].y));
		add(a[i+1].num,a[i].num,abs(a[i+1].y-a[i].y));
	}
	spfa();
	cout<<lu[n]-1;
	return 0;
}
/*
5
2 2
1 1
7 1
4 5
6 7
*/

一道dp

一道小贪心的图论

最后一道是dp

但是用了各种二分找答案

以及空间优化和时间优化

n块木头n-1个点被砍

选择几个点输出最长的木块长度的最小值

最多切成m块

只需要利用单调性优化

考虑到j只能有j-1更新

便能优化了



猜你喜欢

转载自blog.csdn.net/enesama/article/details/79427219