题目链接:传送门
题意:
水果忍者的游戏,给定你n刀,m个水果,以及这一刀切的时间和这一刀可以切的水果的编号,如果两刀之间相隔的时间不超过v,而且这两刀都可以切超过三个水果那么这两刀就可以得一个高分。每个水果只能被切一次,求切的刀的编号使得可以得到最多的连击。
分析:
搜索+剪枝,剪枝就是当前所得到的连击数+剩下所有的刀数小于当前最优的连击数就跳出。
代码如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 35;
struct Fruit_cut{
int num,t,id,c[10];
bool operator <(const struct Fruit_cut &tmp)const{
return t<tmp.t;
}
}cut[maxn];
int n,m,v;
int vis[210];
int ans[maxn],tot,tlong;
int tmp[maxn];
void dfs(int id,int pre){
if(n-id+tlong<=tot) return;
for(int i=id+1;i<=n;i++){
int num = 0;
for(int j=0;j<cut[i].num;j++){
int pos = cut[i].c[j];
if(!vis[pos]) num++;
vis[pos]++;
}
if((cut[i].t-pre<=v||!tlong)&&num>=3){
tmp[tlong++]=cut[i].id;
dfs(i,cut[i].t);
tlong--;
}
for(int j=0;j<cut[i].num;j++){
int pos = cut[i].c[j];
vis[pos]--;
}
}
if(tlong>tot){
tot = tlong;
for(int i=0;i<tlong;i++){
ans[i]=tmp[i];
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&v);
for(int i=1;i<=n;i++){
scanf("%d%d",&cut[i].num,&cut[i].t);
cut[i].id=i;
for(int j=0;j<cut[i].num;j++){
scanf("%d",&cut[i].c[j]);
}
}
sort(cut+1,cut+n+1);
tot=0,tlong=0;
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
dfs(0,cut[1].id);
sort(ans,ans+tot);
printf("%d\n",tot);
for(int i=0;i<tot-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[tot-1]);
}
return 0;
}
</span>