您的位置:首页 > 其它

ZOJ 3305 Get Sauce(DFS+剪枝)

2013-04-30 16:23 351 查看
首先对方式按照材料分类.

然后排序再搜索,详细的看注释.

跑了1.9秒多,可能还有其他的剪枝吧.

#include <iostream>
#include <memory.h>
#include <cstdio>
#include <memory.h>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=17;

vector<int>v1[maxn];//需要这种材料的方式
vector<int>v2[50010];//这种方式需要的材料
bool vis[maxn],vis2[50010][17];
int n,m,ans;
bool cmp(const int a,const int b ){
return v2[a].size()<v2[b].size();
}
void dfs(int mLeft,int cnt){
if(cnt>ans){
ans=cnt;
}else if(mLeft+cnt<ans||!mLeft)return;//剩下的材料就算一个材料一瓶也比当前最优值小,剪掉
int i=0;
for (i=1;i<=n&&vis[i];++i);//找到没有被选掉的第一个材料
if(i>n)return;
for (int j=0;j<v1[i].size();++j){//遍历这个需要这个材料的所有方式
vector<int> &v=v2[v1[i][j]];
if(v.size()>mLeft)return;//因为已经排过序所以如果需要的材料数量大于剩余材料数,剪掉
int f=0;
for (int k=1;k<=n;++k){//判断这种方式需要的材料是否已经被选了
if(vis[k]&&vis2[v1[i][j]][k]){
f=1;
break;
}
}
if(!f){
for (int k=0;k<v2[v1[i][j]].size();++k){//把这种方式需要的材料选掉
vis[v[k]]=1;
}
dfs(mLeft-v2[v1[i][j]].size(),cnt+1);
for (int k=0;k<v2[v1[i][j]].size();++k){//还原
vis[v[k]]=0;
}
}
}
}
int main(){
while (scanf("%d%d",&n,&m)==2){
for (int i=0;i<n;++i){
v1[i].clear();
}
for (int i=0;i<m;++i){
v2[i].clear();
memset(vis2[i],0,sizeof(vis2[i]));
}
for (int i=0;i<m;++i){
int size;
scanf("%d",&size);
while (size--){
int t;
scanf("%d",&t);
v2[i].push_back(t);
v1[t].push_back(i);
vis2[i][t]=1;
}
}
for (int i=0;i<n;++i){
sort(v1[i].begin(),v1[i].end(),cmp);
}
ans=0;
dfs(n,0);
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: