【Luogu】P3786萃香抱西瓜(状压DP)

  题目链接

  水题,数据范围提示得太明显了吧,不用动脑子都能知道是状压。

  不过还是有坑(当然更可能是我脑子有坑)

  f[i][j][k][l]表示当前是第i秒,萃香在(j,k),已经抱到的西瓜状态是l的最少移动次数,然后用BFS一样的办法暴力转移就行,复杂度完全过得去。

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#define maxp 7
#define maxt 105
#define maxn 12
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int f[maxt][maxp][maxp][1<<maxn];
int q[maxt][maxp][maxp];
int tot;
int ux[5]={0,1,0,-1,0};
int wy[5]={0,0,1,0,-1};

int main(){
    int h=read(),w=read(),t=read(),sx=read(),sy=read(),n=read(),m=read();
    int lim=1<<m;
    memset(f,127/3,sizeof(f));    int inf=f[0][0][0][0];
    f[1][sx][sy][0]=0;
    for(int i=1;i<=n;++i){
        int t1=read(),t2=read(),opt=read();
        int to=t2;
        if(t2>t)    t2=t;
        if(opt==1){
            tot++;
            for(int j=t1;j<to;++j){
                int x=read(),y=read();
                q[j][x][y]=tot;
            }
        }
        else{
            for(int j=t1;j<to;++j){
                int x=read(),y=read();
                q[j][x][y]=-1;
            }
        }
    }
    for(int tme=1;tme<=t;++tme){
        for(int i=1;i<=h;++i)
            for(int j=1;j<=w;++j)
                for(register int k=0;k<lim;++k){
                    if(f[tme][i][j][k]==inf)    continue;
                    for(int l=1;l<=4;++l){
                        int x=i+ux[l],y=j+wy[l];
                        if(x==0||y==0||x>h||y>w||q[tme+1][x][y]==-1)    continue;
                        int ret=q[tme+1][x][y],now=0;
                        if(ret)    now=1<<(ret-1);
                        f[tme+1][x][y][k|now]=min(f[tme+1][x][y][k|now],f[tme][i][j][k]+1);
                    }
                    if(q[tme+1][i][j]!=-1){
                        int ret=q[tme+1][i][j],now=0;
                        if(ret)    now=1<<(ret-1);
                        f[tme+1][i][j][k|now]=min(f[tme+1][i][j][k|now],f[tme][i][j][k]);
                    }
                }
    }
    int ans=inf;
    for(int i=1;i<=h;++i)
        for(int j=1;j<=w;++j)
            if(ans>f[t][i][j][lim-1])    ans=f[t][i][j][lim-1];
    if(ans==inf)    ans=-1;
    printf("%d",ans);
}

 

posted @ 2018-01-29 15:10  Konoset  阅读(205)  评论(0编辑  收藏  举报