题意:给出某个时间点会出现的水果,问能最多连续切多少刀使得每一刀都有额外奖励加分(水果数>3)
一个最优化剪枝(当前能获得的最优值还不如以求出的最优解)和一个可行性剪枝(时间间隔<=w)。
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 35
#define maxm 205
int n,m,w,ans;
bool iscut[maxm];
struct node
{
int num,t,id;
int f[15];
}cut[maxn];
int f[maxn],tmp[maxn],way[maxn];
bool cmp(node a,node b)
{
return a.t<b.t;
}
void make(int x,int dep,int sum,int t)
{
if (dep+n-x<=ans) return;
if (dep>ans)
{
ans=dep;
for (int i=0;i<dep;i++) way[i]=tmp[i];
}
if (m-sum<3) return;
for (int i=x+1;i<=n;i++)
{
if (t&&cut[i].t-t>w) break;
int cnt=0,temp[20];
for (int j=1;j<=cut[i].num;j++)
if (!iscut[cut[i].f[j]])
temp[++cnt]=cut[i].f[j];
if (cnt<3) continue;
for (int j=1;j<=cnt;j++)
iscut[temp[j]]=1;
tmp[dep]=cut[i].id;
make(i,dep+1,sum+cnt,cut[i].t);
for (int j=1;j<=cnt;j++)
iscut[temp[j]]=0;
}
}
int main()
{
//freopen("/home/christinass/code/in.txt","r",stdin);
int cas;
scanf("%d",&cas);
while (cas--)
{
scanf("%d%d%d",&n,&m,&w);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&cut[i].num,&cut[i].t);
for (int j=1;j<=cut[i].num;j++)
scanf("%d",&cut[i].f[j]);
cut[i].id=i;
}
sort(cut+1,cut+n+1,cmp);
ans=0;
memset(iscut,0,sizeof(iscut));
make(0,0,0,0);
sort(way,way+ans);
printf("%d\n",ans);
for (int i=0;i<ans;i++)
{if (i) printf(" ");printf("%d",way[i]);}
if (ans) printf("\n");
}
return 0;
}