COJ 1686:记忆化搜索

看了N遍才看懂题意。。。

题意:给N个区间,每次能向左或向右走区间长度这么多,问能不能每次都在[0,m]这个范围内

思路:爆搜是不行的。。这里把状态记录一下能剪枝很多

定义:s[pos][now]=-11分别为“时间now走到pos这个位置是不能、没试过、能走到终点而满足要求”

pos最大是100,now最大是1e4,开得下。然后搜一下就好了

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"set"
#include"vector"
#define ll long long
#define mems(a,b) memset(a,b,sizeof(a))
#define ls pos<<1
#define rs pos<<1|1

using namespace std;
const int MAXN = 120;
const int MAXM = 10050;
const int INF = 0x3f3f3f3f;
int n,m,flag;
int x[MAXN];
int s[MAXN][MAXM];

int dfs(int now,int pos){
    if(pos>=n) return 1;
    if(s[pos][now]) return s[pos][now];
    if(now+x[pos]<=m&&dfs(now+x[pos],pos+1)==1) {s[pos][now]=1;return 1;}
    if(now-x[pos]>=0&&dfs(now-x[pos],pos+1)==1) {s[pos][now]=1;return 1;}
    s[pos][now]=-1;
    return -1;
}

int main(){
    //freopen("in.txt","r",stdin);
    int f;
    scanf("%d",&f);
    int ok=1;
    while(f--){
        scanf("%d%d",&m,&n);
        for(int i=0;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            x[i]=b-a;
        }
        mems(s,0);
        flag=0;
        for(int i=0;i<=m;i++){
            if(dfs(i,0)==1) flag=1;
            if(flag) break;
        }
        if(!flag) ok=0;
    }
    if(ok) printf("possible
");
    else printf("impossible
");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/luxiaoming/p/5264116.html