poj 1010 STAMPS 解題報告 -- 搜索 遍歷 剪枝

好吧。。這題很鬱悶。。。一直不知道怎麼就WA了,後來看到別人說數組開大點。。。就AC了。。。這不是坑麼。。。


題目大意:

給出n種郵票,每種郵票有自己的面值(面值可能重複)
  指定m種“總面值”,對每種“總面值”,求解滿足如下條件的組合以達到該“總面值”
(1) 所用郵票在n種中可以重複選取
(2) 所用郵票張數〈=4
(3) 儘量多的使用那個不同種類的郵票 Max (Stamp Types)
(4) 若有多種方案滿足(3),則選取張數最小的一種方案 Min (Stamp Num)
(5) 若有多種方案滿足(3)(4),則選取“最大面額”最高的一種方案。 Max(Heightest Value)
(6) 若有多種方案滿足(3)(4)(5) 則輸出 “tie” 1010


思路:

就直接遍歷了,再進行一點剪枝。由於限定了張數是4張,也就直接模擬了,沒有用遞歸啊棧啊一流。。。naive。。。



代碼:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

#define TYPE_NUM 100

int s_type[TYPE_NUM];

int p[5];
int need[5];
int record_p[5];

int g_tn;
int g_mn;
int g_mv;
bool tie_flag;

void ini_type()
{
	memset(s_type,0,TYPE_NUM);
}
void ini_record()
{
	memset(record_p,0,5);
}
void write_record()
{
	copy(p,p+5,record_p);
}
void ini_value()
{
	g_tn = 0; g_mn = 0;
	g_mv = 0; tie_flag = false;
	ini_record();
}

int set_best(int tn , int mn ,int mv)//1: success  0: tie  -1: fail
{
	if(tn>g_tn)
	{
		g_tn = tn;
		g_mn = mn;
		g_mv = mv;
		tie_flag = false;
		write_record();
		return 1;
	}
	if(tn == g_tn)
	{
		if(mn < g_mn)
		{
			g_mn = mn;
			g_mv = mv;
			tie_flag = false;
			write_record();
			return 1;
		}
		if(mn == g_mn)
		{
			if(mv > g_mv)
			{
				g_mv = mv;
				tie_flag = false;
				write_record();
				return 1;
			}
			if(mv == g_mv)
			{
				tie_flag = true;
				return 0;
			}
		}
	}
	return -1;
}

void get_match( int n )
{
	int tn[5] ,mv;

	for(p[1] = n; p[1] >= 1 ; p[1] --)
	{
		tn[1]=1;
		mv = s_type[p[1]];
		if(s_type[p[1]] >= need[1])
		{
			if(s_type[p[1]] == need[1])
				set_best(tn[1],1,mv);
			continue;
		}

		need[2] = need[1] - s_type[p[1]];
		for(p[2] = p[1]; p[2] >= 1 ; p[2] --)
		{
			if(p[2] == p[1])
			{
				tn[2] = tn[1];
			}
			else
			{
				tn[2] = tn[1]+1;
			}
			if(s_type[p[2]] >= need[2])
			{
				if(s_type[p[2]] == need[2])
					set_best(tn[2],2,mv);
				continue;
			}

			need[3] = need[2] - s_type[p[2]];
			for(p[3] = p[2]; p[3] >= 1; p[3] --)
			{
				if(p[3] == p[2])
				{
					tn[3] = tn[2];
				}
				else
				{
					tn[3] = tn[2]+1;
				}
				if(s_type[p[3]] >= need[3])
				{
					if(s_type[p[3]] == need[3])
						set_best(tn[3],3,mv);
					continue;
				}

				need[4] = need[3] - s_type[p[3]];
				for(p[4]= p[3]; p[4] >= 1; p[4] --)
				{
					if(p[4] == p[3])
					{
						tn[4] = tn[3];
					}
					else
					{
						tn[4] = tn[3]+1;
					}
					if(s_type[p[4]] >= need[4])
					{
						if(s_type[p[4]] == need[4])
						{
							set_best(tn[4],4,mv);
							if(tie_flag == true && tn[4] == 4)
								return ;
						}
					}
				}
			}
		}
	}
}

int main()
{
	int c,n=0;
	int i;

	freopen("in.txt","r",stdin);

	while(EOF != scanf("%d",&c))
	{
		s_type[n++] = c;
		if(c == 0)
		{
			sort(&s_type[0],&s_type[n]);
			scanf("%d",&c);			
			while(0 != c)
			{			
				need[1] = c;
				get_match(n-1);
				if(g_tn == 0)
					printf("%d ---- none\n",c);
				else
					if(tie_flag == true)
						printf("%d (%d): tie\n",c,g_tn);
					else
					{
						printf("%d (%d): ",c,g_tn);
						for(i=g_mn;i>=1;i--)
						{
							printf("%d ",s_type[record_p[i]]);
						}
						printf("\n");
					}

				ini_value();
				scanf("%d",&c);
			}
			n=0;
			ini_type();
		}
	}

	return 0;
}


發佈了26 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章