NOIP2014飞扬的小鸟

好久没写博客啦。发几篇最近做过的题。

这道题显然是背包,选择跳几次或不跳。暴力打背包是70分。
如果填表法:我们发现转移的时候如果不考虑下降,那么上升的可以同列转移
(f【i】【j】转移到f【i】【j+k】)所以先转移上升的再转移下降的,最后填充非法情况。

对于刷表法:会刷到重复的状态,如果值不优,就停止刷表,因为一定不会更优了。

最后WA的原因——没处理好越界后高度维持上限的问题。

int gg=(m-j)/up[i]+1;
for(int k=1;k<=gg;k++){
int md=min(m,j+k*up[i]);//比较精髓的处理方式,上限和枚举的取最小值。
#include
using namespace std;

const int MAXN=1e3+5;

int f[MAXN*10][MAXN];//f[i][j]表示横坐标i,纵坐标j最小点击次数
int n,m,k;//长度,高度,水管数。 

int up[MAXN*10],down[MAXN*10];
int limitup[MAXN*10],limitdown[MAXN*10],ansnum=0;
bool limit[MAXN*10],vis[MAXN*10];

void mem(int n){
    memset(f,0x3f,sizeof(f));
    memset(limit,0,sizeof(limit));
    memset(vis,0,sizeof(vis));
    memset(limitup,0,sizeof(limitup));
    memset(limitdown,0,sizeof(limitdown));
    for(int i=0;i<=n;i++)f[0][i]=0;
} 

int main(){
    scanf("%d%d%d",&n,&m,&k);
    mem(m);
    for(int i=0;iscanf("%d%d",&up[i],&down[i]);
    }
    for(int i=0;iint tem1,tem2,tem3;
        scanf("%d%d%d",&tem1,&tem2,&tem3);
        limit[tem1]=1;
        limitdown[tem1]=tem2;
        limitup[tem1]=tem3;
    }
    int tem1=0;
    for(int i=0;ifor(int j=m;j>=0;j--){//当前状态的高度 
            if(limit[i]&&j<=limitdown[i])continue;
            else if(limit[i]&&j>=limitup[i])continue;
            else if(f[i][j]==1061109567)continue;
            if(limit[i]&&!vis[i]){
                vis[i]=1;ansnum++;  
            }
            int gg=(m-j)/up[i]+1;
            for(int k=1;k<=gg;k++){
                int md=min(m,j+k*up[i]);
                if((limit[i+1]&&j+k*up[i]>limitdown[i+1]&&j+k*up[i]1])||!limit[i+1])
                if(f[i][j]+k1][md])f[i+1][md]=f[i][j]+k;
                else break;
            }
            if(j-down[i]>0){
            //  cout<
            //  if(!i)cout<
                //if(i==0)cout<
                if((limit[i+1]&&j-down[i]>limitdown[i+1]&&j-down[i]1])||!limit[i+1])f[i+1][j-down[i]]=min(f[i+1][j-down[i]],f[i][j]);
            }
        }
    }
    int ans=1061109567;
    for(int i=0;i<=m;i++)ans=min(ans,f[n][i]);
    if(ans!=1061109567)printf("1\n%d\n",ans);
    else printf("0\n%d\n",ansnum);
    return 0;
}

你可能感兴趣的:(DP)