您的位置:首页 > 其它

usaco Healthy Holsteins individual report

2015-08-16 16:43 302 查看
由于每一种维生素的含量都会制约选择,所以通过搜索来找到最佳的选择几乎是必须。

初始想法是先考虑一种,逐渐再考虑更多的种数,如果有符合的就在这一层停止搜索。

实现过程中,问题是,如何把2^15种情况按种类增加的顺序搜索。

一种方法是状态压缩,用一个数字的不同位数信息来表示一个较大的数组或者其他需求空间很大或操作时间很长的数据结构。

用2^n逐一枚举,利用&运算判断第几个位置也是第几种饲料是否被选择,对应的情况如果满足再看其种类数是否小于应经记录的,如果是则当前最优的是这个方案。

当然这样也就不是逐层搜索了

第二种方法:

利用dfs实现,决策是选择下一个饲料。
void dfs(int c)
{
int i,j;
if(n==0)    //搜索到最底层
return;
for(i=0;i<m;i++)    //判断当前是否满足
{
int s;
for(j=0;j<n;j++)
{
if(xuan[j])
s+=sl[j][i];
}
if(s<ve[i])
break;
}
if(i==m)
{
//记录
return ;
}
for(i=0;i<n;i++)
{
if(xuan[i]==0)
{
xuan[i]=1;
dfs(c-1);
xuan[i]=0;
}
}
}

以上是自己写的dfs缺点在于重复搜索了很多情况,如果记录下每次搜索的当前种子、和达到的层数,来实现字典序下的搜索。

代码如下

#include <stdio.h>
int cur[16]={0};int num=5;
void find_feed(int n,int m)
{

if(n>=num)
return;
while(n<num)
{
cur[m]=n;
//for(int i=0;i<=m;i++)   打印部分,看不懂的可以查看理解
//printf("%d ",cur[i]);
//printf("\n");
find_feed(n+1,m+1);
n++;
}
}
int main()
{

find_feed(0,0);
return 0;
}


这样做出来的问题是,仍然不能按层数递进搜索,同时判重操作(没有写)花费很大的空间,当然可以用状态压缩来判重。

第三种方法:bfs也是利用二进制判重,关键在于搜索顺序随着层数增加
while(front1!=rear)
{
temp=Dequeue();//队首元素处理
printf("%d:\n",temp);
Invert(temp);//数字转化为选择序列
if(judge())
break;
for(i=0;i<G;i++)
{
if(NowChoose[i]!=1)
{
NowChoose[i]++;
temp=change();//序列转化为数字
if(flag[temp]!=1)//判重
{
Enqueue(temp);//待处理项进队
flag[temp]=1;
NowChoose[i]--;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  usaco 算法