#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更新
便能优化了