[noip2014tg] 飞扬的小鸟

题解:看到题目,二话不说就写了个爆搜,拿了50,后来优化了一下,改成了记忆化,O(nm^2),惨遭卡常数(写得太丑了),只有60
dp等以后在写吧,我太弱了QAQ

爆搜

#include <iostream>
#include <cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int M=50;
int n,m,k;
int ans=INF,dis;
int x[M],y[M];
int vis[M][M];
struct pipe{
    int p,l,h;
}pi[M];
void init()
{
    cin>>n>>m>>k;
    for(int i=0;i<n;i++)
    scanf("%d%d",&x[i],&y[i]);
    for(int i=1;i<=k;i++){
        scanf("%d%d%d",&pi[i].p,&pi[i].l,&pi[i].h);
        for(int j=1;j<=pi[i].l;j++)
        vis[pi[i].p][j]=1;
        for(int j=m;j>=pi[i].h;j--)
        vis[pi[i].p][j]=1;
    }
}
void dfs(int pos,int high,int tm)
{
    if(high>m) high=m;
    if(high<=0) return ;
    if(vis[pos][high]==1) return ;
    dis=max(dis,pos);
    if(pos==n){
        ans=min(ans,tm);
        return ;
    }
    int tal=0,j=0;
    do
    {
        tal+=x[pos];j++;
        dfs(pos+1,high+tal,tm+j);
    }while(j<=3&&high+tal<=m);
    dfs(pos+1,high-y[pos],tm);
}
void work()
{
    for(int i=1;i<=m;i++)
    dfs(0,i,0);
    if(ans!=INF){
        cout<<"1"<<endl;
        cout<<ans<<endl;
        return ;
    }
    int tot=0;
    for(int i=1;i<=k;i++)
    if(pi[i].p<=dis) tot++;
    cout<<"0"<<endl;
    cout<<tot<<endl;
}
int main()
{
    init();
    work();
}

记忆化

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
const int M=1050;
int n,m,k;
int ans=INF,dis;
int x[M],y[M];
int vis[M][M],f[M][M];
struct pipe{
    int p,l,h;
}pi[M];
void init()
{
    cin>>n>>m>>k;
    for(int i=0;i<n;i++)
    scanf("%d%d",&x[i],&y[i]);
    for(int i=1;i<=k;i++){
        scanf("%d%d%d",&pi[i].p,&pi[i].l,&pi[i].h);
        for(int j=1;j<=pi[i].l;j++)
        vis[pi[i].p][j]=1;
        for(int j=m;j>=pi[i].h;j--)
        vis[pi[i].p][j]=1;
    }
}
int dfs(int pos,int high)
{
    if(high>m) high=m;
    if(high<=0) return INF;
    if(vis[pos][high]==1) return INF;
    if(pos==n) return 0;
    dis=max(dis,pos);
    if(f[pos][high]>0&&f[pos][high]!=INF) return f[pos][high];
    int tal=0,j=0;
    do
    {
        tal+=x[pos];j++;
        f[pos][high]=min(f[pos][high],dfs(pos+1,high+tal)+j);
    }while(high+tal<=m);
    f[pos][high]=min(f[pos][high],dfs(pos+1,high-y[pos]));
    return f[pos][high];
}
void work()
{
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=m;i++)
    ans=min(ans,dfs(0,i));
    if(ans!=INF){
        cout<<"1"<<endl;
        cout<<ans<<endl;
        return ;
    }
    int tot=0;
    for(int i=1;i<=k;i++)
    if(pi[i].p<=dis) tot++;
    cout<<"0"<<endl;
    cout<<tot<<endl;
}
int main()
{
    init();
    work();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值