HDU 4620 Fruit Ninja Extreme 搜索

搜索+最优性剪枝。

DFS的下一层起点应为当前选择的 i 的下一个,即DFS(i + 1)而不是DFS( cur + 1 ),cur+1代表当前起点的下一个。没想清楚,TLE到死……

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 const int MAXN = 40;
  9 
 10 struct node
 11 {
 12     int t, id;
 13     int cnt;
 14     int fruit[12];
 15 };
 16 
 17 int N, M, W;
 18 int ansN, tmpN;
 19 node D[MAXN];
 20 int tmp[MAXN];
 21 int ans[MAXN];
 22 bool vis[320];
 23 
 24 bool cmp( node a, node b )
 25 {
 26     return a.t < b.t;
 27 }
 28 
 29 void chuli( int cnt )
 30 {
 31     for ( int i = 0; i < cnt; ++i )
 32         ans[i] = tmp[i];
 33     return;
 34 }
 35 
 36 int change( int i, int *temp )
 37 {
 38     int cnt = 0;
 39     for ( int j = 0; j < D[i].cnt; ++j )
 40     {
 41         int idx = D[i].fruit[j];
 42         if ( !vis[ idx ] )
 43             temp[cnt] = idx, ++cnt;
 44     }
 45     return cnt;
 46 }
 47 
 48 void MyRestore( int *temp, int cnt )
 49 {
 50     
 51     for ( int j = 0; j < cnt; ++j )
 52     {
 53         vis[ temp[j] ] = false;
 54     }
 55     return;
 56 }
 57 
 58 void DFS( int cur, int pre, int sum )
 59 {
 60     if ( tmpN > ansN )
 61     {
 62         ansN = tmpN;
 63         chuli( tmpN );
 64     }
 65     if ( cur >= N ) return;
 66     if ( tmpN + N - cur <= ansN ) return;
 67     if ( M - sum < 3 ) return;
 68 
 69     for ( int i = cur; i < N; ++i )
 70     {
 71         if ( pre != -1 && D[i].t - D[pre].t > W ) break;
 72 
 73         if ( D[i].cnt < 3 ) continue;
 74         int temp[20];
 75         int left = change( i, temp );
 76         if ( left < 3 ) continue;
 77 
 78         for ( int j = 0; j < left; ++j )
 79         {
 80             int idx = temp[j];
 81             vis[idx] = true;
 82         }
 83 
 84         tmp[ tmpN++ ] = D[i].id;
 85         DFS( i + 1, i, sum + left );  //i+1 不是 cur+1 !!!!!
 86         --tmpN;
 87         MyRestore( temp, left );
 88     }
 89 
 90     return;
 91 }
 92 
 93 int main()
 94 {
 95     //freopen( "1010.in", "r", stdin );
 96     //freopen( "s.out", "w", stdout );
 97     int T;
 98     scanf( "%d", &T );
 99     while ( T-- )
100     {
101         scanf( "%d%d%d", &N, &M, &W );
102         for ( int i = 0; i < N; ++i )
103         {
104             D[i].id = i + 1;
105             scanf("%d%d", &D[i].cnt, &D[i].t );
106             for ( int j = 0; j < D[i].cnt; ++j )
107                 scanf( "%d", &D[i].fruit[j] );
108         }
109         sort( D, D + N, cmp );
110 
111         ansN = 0;
112         tmpN = 0;
113         memset( vis, false, sizeof(vis) );
114         DFS( 0, -1, 0 );
115 
116         sort( ans, ans + ansN );
117         printf( "%d\n", ansN );
118         for ( int i = 0; i < ansN; ++i )
119         {
120             if ( i ) putchar(' ');
121             printf( "%d", ans[i] );
122         }
123         puts("");
124     }
125     return 0;
126 }

 

转载于:https://www.cnblogs.com/GBRgbr/p/3221247.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值