1. 程式人生 > 其它 >P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins做題筆記

P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins做題筆記

感覺自己 \(BFS\) 還是太弱了,考試時只會寫 \(DFS\),連 \(BFS\) 的基本思路和原理都比較模糊,所以最近開始練 \(BFS\)。這道題鴿了很久了,以前練 \(BFS\) 的時候看題解覺得碼量偏大就換題了,咕到了現在。開始時沒想出來,可能有以前看題的心理陰影在裡面吧,然後就看了題解。思路是建一個結構體的佇列,結構體裡兩個陣列一個變數,分別表示當前各種維他命的量、用了哪幾種飼料以及用的飼料總數,先把只用一種飼料的情況按字典序入隊,進行 \(BFS\),判斷是否有單個飼料滿足情況,即每一種維他命量都大於所需的維他命最小量,如果有就輸出並停止搜尋,否則遍歷字典序在當前飼料後面的飼料,把後面的一種飼料加入當前飼料中,將所有加入飼料的情況入隊。注意

:不能在直接表示當前飼料維他命量的陣列上直接加上後來的飼料,這會造成累加,無法保證飼料的總數最小,要用一個結構體備份表示當前飼料的結構體,在加後面的飼料時把當前飼料賦值為備份的當前飼料加後來的飼料。

#include <bits/stdc++.h>
  using namespace std;
int m,n,a[20][30],b[30],i,j;
bool v;
struct xy{
	int x[30],y[400],z;
}t,u;
queue<xy>q;
void bfs()
{
	int k,l;
	for (k=1;k<=n;k++)
	{
		for (l=1;l<=m;l++)
		{
			t.x[l]=a[k][l];
		}
		t.y[1]=k;
		t.z=1;
		q.push(t);
	}
	while (!q.empty())
	{
		t=q.front();
		u=q.front();
		q.pop();
		v=1;
		for (k=1;k<=m;k++)
		{
			if (u.x[k]<b[k])
			{
				v=0;
				break;
			}
		}
		if (v)
		{
			cout<<u.z<<" ";
			for (k=1;k<=t.z;k++)
			{
				cout<<u.y[k]<<" ";
			}
			cout<<endl;
			return;
		}
		for (k=u.y[u.z]+1;k<=n;k++)
		{
			for (l=1;l<=m;l++)
			{
				t.x[l]=u.x[l]+a[k][l];
			}
			t.z=u.z+1;
			t.y[t.z]=k;
			q.push(t);
		}
	}
}
int main()
{
	ios::sync_with_stdio(0); cin.tie(nullptr);
	cin>>m;
	for (i=1;i<=m;i++)
	{
		cin>>b[i];
	}
	cin>>n;
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			cin>>a[i][j];
		}
	}
	bfs();
	return 0;
}