【线性动态规划】

1>尼克的任务

额一道挺水的题,愣是做了几个小时

 

动态规划大致的思路还是找一个转移

换个词就是影响

 

我们可以明显看出本题的规则:

空暇时,一遇到任务必须挑一个接

1-n时间内最大空暇时间

所以将任务排序是必要的,两个关键字

 

再来想象一下当我做到第i个任务时,我在st[i]-st[i]+t[i]-1)时必然在工作

那么1-(st[i]+t[i]-1)的区间内,

是我上一个任务的f[j]和与j任务之间的时间空暇决定的

则现在的问题是,找出所以合法j任务,然后加上st[i]-st[j]-t[j]

 

合法的j任务应该满足什么要求呢

st[i]之前已经完成,但是又不能已经完成了太久

这个不能完成太久的条件,其实正着推最容易,

就是j+1任务往后数,最先开始的那个就是,

所以我们需要一个新数组,预处理这个最先开始

 

当然其实我可以不要这个数组

只要每个当前任务点,去更新后面的任务点

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring> 
using namespace std;
int m,n;
const int N=10003;
struct node
{
    int st,ed;//这里是左闭合,右开 
    bool operator < (const node & o) const
    {
        if(st!=o.st) return st<o.st;
        else return ed<o.ed;
    }
}d[N];
int f[N];

int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&d[i].st ,&d[i].ed ),d[i].ed +=d[i].st ;
    d[++n].st =m+1,d[n].ed =m+1;
    sort(d+1,d+n);
    
    memset(f,-1,sizeof(f));
    int i=2;
    f[1]=d[1].st -1;
    while(i<n && d[i].st ==d[1].st ) f[i++]=f[1];
    
    for(i=1;i<n;i++)
    {
        if(f[i]==-1) continue;
        int nx=i+1;
        while(nx<n && d[nx].st <d[i].ed ) nx++;
        
        //printf("%d %d\n",d[i].st ,d[i].ed );
        int dis=d[nx].st -d[i].ed ;
        for(int j=nx;j<=n && d[j].st ==d[nx].st ;j++)
        {
            f[j]=max(f[i]+dis,f[j]);
            //,printf(" %d %d %d\n",d[j].st ,d[j].ed ,f[j]);
            //if(d[j].st ==9994) printf("%d %d %d\n",i,f[i],dis);
        }
    }
    
    printf("%d\n",f[n]);
    return 0;
} 

 

//倒序做
//为什么? 
#include<cstdio>
#include<cstdlib>
#include<algorithm> 
#include<vector>
using namespace std;
int m,n;
const int N=10003;
vector <int> t[N];
int f[N];

int main()
{
    scanf("%d%d",&m,&n);
    int st,ed;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&st ,&ed ),ed +=st ,t[st ].push_back(ed);
    
    for(int i=m;i;i--)
    {
        int sz=t[i].size();
        if(!sz) 
        {
            f[i]=f[i+1]+1;
            continue;
        }
        for(int j=0;j<sz;j++)
        {
            ed=t[i][j];
            f[i]=max(f[i],f[ed ]);
        }
    }
    
    printf("%d\n",f[1]);
    return 0;
} 

 

2>相似基因

#include<cstdio>
#include<cstdlib>
#include<iostream> 
#include<cstring> 
using namespace std;
int n1,n2;
const int N=103;
char s1[N],s2[N];
int d1[N],d2[N];
const int tab[5][5]=
{
    {5,-1,-2,-1,-3},
    {-1,5,-3,-2,-4},
    {-2,-3,5,-2,-2},
    {-1,-2,-2,5,-1},
    {-3,-4,-2,-1,0}
};
int f[N][N];

int main()
{
    scanf("%d%s",&n1,s1+1);
    scanf("%d%s",&n2,s2+1);
    for(int i=1;i<=n1;i++)
    {
        if(s1[i]=='A') d1[i]=0;
        else if(s1[i]=='C') d1[i]=1;
        else if(s1[i]=='G') d1[i]=2;
        else if(s1[i]=='T') d1[i]=3;
    }
    for(int i=1;i<=n2;i++)
    {
        if(s2[i]=='A') d2[i]=0;
        else if(s2[i]=='C') d2[i]=1;
        else if(s2[i]=='G') d2[i]=2;
        else if(s2[i]=='T') d2[i]=3;
    }
        
    memset(f,-0x3f,sizeof(f));
    f[0][0]=0;for(int i=1;i<=n2;i++) f[0][i]=f[0][i-1]+tab[d2[i]][4];
    for(int i=1;i<=n1;i++) f[i][0]=f[i-1][0]+tab[d1[i]][4];
    
    for(int i=1;i<=n1;i++)
        for(int j=1;j<=n2;j++)
    {
        f[i][j]=max(f[i-1][j-1]+tab[d1[i]][d2[j]],
            max(f[i-1][j]+tab[d1[i]][4],  f[i][j-1]+tab[d2[j]][4]) );
        //printf("%d %d %d\n",f[i-1][j-1]+tab[d1[i]][d2[j]],f[i-1][j]+tab[d1[i]][4],f[i][j-1]+tab[d2[j]][4]);
        //printf("%d\n",f[i][j]);
    }
    
    printf("%d\n",f[n1][n2]);
    return 0;
}

 

转载于:https://www.cnblogs.com/xwww666666/p/11357205.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值