HDU 4620 - Fruit Ninja Extreme (DFS)

16 篇文章 0 订阅

Fruit Ninja Extreme

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1136    Accepted Submission(s): 305
Special Judge


Problem Description
  Cut or not to cut, it is a question.
  In Fruit Ninja, comprising three or more fruit in one cut gains extra bonuses. This kind of cuts are called bonus cuts.
  Also, performing the bonus cuts in a short time are considered continual, iff. when all the bonus cuts are sorted, the time difference between every adjacent cuts is no more than a given period length of W.
  As a fruit master, you have predicted the times of potential bonus cuts though the whole game. Now, your task is to determine how to cut the fruits in order to gain the most bonuses, namely, the largest number of continual bonus cuts.
  Obviously, each fruit is allowed to cut at most once. i.e. After previous cut, a fruit will be regarded as invisible and won't be cut any more.
  In addition, you must cut all the fruit altogether in one potential cut. i.e. If your potential cut contains 6 fruits, 2 of which have been cut previously, the 4 left fruits have to be cut altogether.
 

Input
  There are multiple test cases.
  The first line contains an integer, the number of test cases.
  In each test case, there are three integer in the first line: N(N<=30), the number of predicted cuts, M(M<=200), the number of fruits, W(W<=100), the time window.
  N lines follows.
  In each line, the first integer Ci(Ci<=10) indicates the number of fruits in the i-th cuts.
  The second integer Ti(Ti<=2000) indicate the time of this cut. It is guaranteed that every time is unique among all the cuts.
  Then follow Ci numbers, ranging from 0 to M-1, representing the identifier of each fruit. If two identifiers in different cuts are the same, it means they represent the same fruit.
 

Output
  For each test case, the first line contains one integer A, the largest number of continual bonus cuts.
  In the second line, there are A integers, K1, K2, ..., K_A, ranging from 1 to N, indicating the (Ki)-th cuts are included in the answer. The integers are in ascending order and each separated by one space. &#160;If there are multiple best solutions, any one is accepted.
 

Sample Input
  
  
1 4 10 4 3 1 1 2 3 4 3 3 4 6 5 3 7 7 8 9 3 5 9 5 4
 

Sample Output
  
  
3 1 2 3
 

Source
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:   4846  4845  4844  4843  4842


题意:切水果

输入 n m  w ,表示接下来有n刀可以切,有m个水果,w表示每两刀之间的时间间隔

然后以下n行 每行输入 c t c1 c2 c3... c表示一刀切的水果个数 t表示这一刀在什么时候切 后面就是切的水果的编号 

然后题目就是问 最多可以选择切哪几刀,这几刀满足:1.每一刀至少切3个水果 2.这几刀按时间顺序排序后,每两刀之间的时间间隔不能大于w

还有就是 比如第一刀切水果1 3 4 第3刀切3 6 8如果切了第一刀 第3刀就不能切了,因为3已经被切掉了


思路:

因为m<=100 所以DP不行了 因为n比较小 每两个之间约束条件较多 所以直接按时间排序后dfs每刀切还是不切。思路比较简单 但是WA了好久!!


遇到的问题:

第一发TLE 然后加个剪枝 如果剩下的每一刀都切得到的总刀数比当前已有的答案还大 那么这个就可以剪掉

然后WA 无限WA 

中间的错误:

1.时间问题,因为我是全局变量来记时间的(之前sb的觉得这有节约空间,整个dfs最深也就n!),所以忘了调整时间

2.还是时间问题,这个WA了好久然后写对拍才发现 我用一个全局变量记录上次切的是什么时候,在DFS之前初始化为第一刀的时间,在DFS中忘了考虑如果第一刀没有切,那么上次切的时间就不应该是第一刀的时间!!



#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define S64I1(a) scanf(iform1, &(a))
#define P64I1(a) printf(oform1, (a))
#define FOR(i, s, t) for(int (i)=(s); (i)<(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 30 + 5;
const int maxm = 200 + 20;

struct Cut {
    int ord, t;
    vector<int> fruits;
};

int n, m, w;
Cut cuts[maxn];
int vis[maxm];
int ans;
int ansA[maxn];
int tansA[maxn];
int tlastT;

bool cmpByT(Cut a, Cut b) {
    return a.t < b.t;
}

void dfs(int cur, int num) {
    if(cur == n) {
        if(num > ans) {
            ans = num;
            for(int i=0; i<num; i++) {
                ansA[i] = tansA[i];
            }
        }
        return ;
    }
    if(cur >= n || num+n-cur<ans) return ;
    int tlev = 0;
    for(int i=0; i<cuts[cur].fruits.size(); i++) if(vis[cuts[cur].fruits[i]] == 0) {
        tlev++;
    }
    if(tlev >= 3 && cuts[cur].t - tlastT <= w) {
        for(int i=0; i<cuts[cur].fruits.size(); i++) {
            vis[cuts[cur].fruits[i]]++;
        }
        tansA[num] = cuts[cur].ord;
        int oldt = tlastT;
        tlastT = cuts[cur].t;
        dfs(cur+1, num+1);
        tlastT = oldt;
        for(int i=0; i<cuts[cur].fruits.size(); i++) {
            vis[cuts[cur].fruits[i]]--;
        }
    }
    if(tlastT == cuts[cur].t) { // 这里忘了考虑 导致错误2
        tlastT = cuts[cur+1].t;
    }
    dfs(cur+1, num);
}

int main() {
    int T;

    scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d", &n, &m, &w);
        for(int i=0; i<n; i++) {
            int c;
            cuts[i].fruits.clear();
            cuts[i].ord = i+1;
            memset(vis, 0, sizeof(vis));
            scanf("%d%d", &c, &cuts[i].t);
            for(int j=0; j<c; j++) {
                int ci;
                scanf("%d", &ci);
                if(!vis[ci]) {
                    cuts[i].fruits.push_back(ci);
                    vis[ci] = 1;
                }
            }
        }
        sort(cuts, cuts+n, cmpByT);
        memset(vis, 0, sizeof(vis));
        tlastT = cuts[0].t;
        ans = 0;
        dfs(0, 0);
        sort(ansA, ansA+ans);
        printf("%d\n", ans);
        for(int i=0; i<ans; i++) {
            if(i) putchar(' ');
            printf("%d", ansA[i]);
        }
        //if(!ans) printf("0");
        putchar('\n');
    }

    return 0;
}



 






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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值