您的位置:首页 > 其它

dp day 4 斜率优化(fa)bzoj1597+简单dp问题

2018-03-01 21:39 387 查看
地主zxr想买一些长方形的土地,所有的土地可以分为若干组,每一组的土地的价格为这一组里的最长的长乘上最长的宽。土地的长和宽是不能交换的,例如一块2*5的土地和一块5*2的土地放在一起,价格为5*5=25。ZXR想知道最少花费多少钱可以买下所有的土地。
Input:
        第一行一个数n表示一共有n块土地。
            接下来n行每行两个数xi和yi分别表示每块土地的长和宽。
Output:
        一行一个数表示最小价格
先sort一遍如果它的y值也比数组的y值小的化那么这个点对于更新答案没有作用就删去tot--
最后由dp[i]=dp[j]+x[i]*y[i+1]可以推出dp[j]-dp[k]<=x[i]*(y[k+1]-y[j+1])就可以进行斜率优化了
粘上代码#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=50005;

struct p
{
long long x,y;
}node[maxn];

long long n,x[maxn],y[maxn],tot=0,dp[maxn],q[maxn];

bool cmp(p a,p b)
{
return a.x==b.x?a.y<b.y:a.x<b.x;
}

double xielv(int k,int j)
{
return (double)(1.0*dp[j]-1.0*dp[k])/(1.0*y[k+1]-1.0*y[j+1]);
}

int main()
{
freopen("buy.in","r",stdin);
freopen("buy.out","w",stdout);
scanf("%I64d",&n);
for (int i=1;i<=n;i++)
scanf("%I64d%I64d",&node[i].x,&node[i].y);
sort(node+1,node+n+1,cmp);
for (int i=1;i<=n;i++)
{
while (tot&&node[i].y>=y[tot])
tot--;
x[++tot]=node[i].x;
y[tot]=node[i].y;
}
int head=1,tail=0;
q[++tail]=0;
for (int i=1;i<=tot;i++)
{
while (head<tail&&xielv(q[head],q[head+1])<x[i])
head++;
int tmp=q[head];
dp[i]=dp[tmp]+x[i]*y[tmp+1];
while (head<tail&&xielv(q[tail],i)<xielv(q[tail-1],q[tail]))
tail--;
q[++tail]=i;
}
printf("%I64d",dp[tot]);
return 0;
}滑(fa)雪

tony在一片雪地里滑雪,他从(1,1)出发,并只能从高的地方滑到低的地方,贪玩的tony想知道他到底能滑多远呢?
Input:
        第一行两个数n,m表示雪地大小。
            接下来n行每行m个数表示雪地,其中w[i][j] = x表示在i,j位置的高度为x,每个位置(除了边界)都可以滑到它的上下左右四个方向(从高往低)。
很基础的dp问题数据过小直接记忆化搜索#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=305;

const int zl[4][2]={{0,1},{0,-1},{-1,0},{1,0}};

int jz[maxn][maxn],ans,f[maxn][maxn];

int max(int a,int b)
{
if (a>b)
return a;
return b;
}

int n,m;

int find(int x,int y)
{
int rt=0;
if (f[x][y]>0)
return f[x][y];
for (int i=0;i<=3;i++)
{
int xx=x+zl[i][1];
int yy=y+zl[i][0];
if (xx>=1&&xx<=n&&yy>=1&&yy<=m&&jz[xx][yy]<jz[x][y])
rt=max(rt,find(xx,yy));
}
return f[x][y]=rt+1;
}

int main()
{
freopen("slide.in","r",stdin);
freopen("slide.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&jz[i][j]);
ans=find(1,1);
printf("%d\n",ans);
return 0;
}tom想知道,把一个整数n划分为若干个正整数的形式,一共有多少种方案。例如当n=4时,他有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};
input:
        一行一个数n。
Output:
        一行一个数表示方案数。
这道题有点傻逼啊记下了i这个数分成j个结果没有去重全wa非常开心#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=5005;

const int Mod=1e9+7;

int dp[maxn][maxn];

int n;
int main()
{
freopen("divide.in","r",stdin);
freopen("divide.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
dp[i][1]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (i==j)
dp[i][j]=1+dp[i][i-1];
else if (i<j)
dp[i][j]=dp[i][i];
else
dp[i][j]=dp[i-j][j]+dp[i][j-1];
dp[i][j]%=Mod;
}
printf("%d\n",dp

);
return 0;
}斜率优化证明有点夸张但是nlogn的决策单调性又不算很好写(懒癌晚期)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: