您的位置:首页 > 其它

poj1010 dfs/枚举

2016-02-19 23:38 369 查看
题意:

给出不同类型的一组邮票,不同类型的邮票面值可能相同。求符合用户输入面值,且最多取4张邮票的最佳方案。最佳方案满足以下要求:

类型数最多。

如果类型数相同,则张数少者。

如果张数也相同,则单张面值最大者。

如果以上都相同,则无最佳方案(平局)。

如果不能达到用户的输入面值,则输出none。

难度:**

算法:

1.dfs
2.暴搜(枚举)

/*
dfs:注意剪枝
*/
#include<stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;

int stamp_val[100]; // stamp_val[i]=j:第i类邮票的面额是j
int request[100]; // request[i]=j:第i位顾客的需求是j
int best_ans[5]; // 记录最佳答案
int curr_ans[5]; // 记录当前答案
bool visited[100]; // 访问标志

int max_types; // 最大类型数
int min_stamp_num; // 最少张数
int highest_val; // 最大面额
bool isTie; // tie标志
int stamp_num; // 邮票总数, stamp_val数组的长度

// 更新最优解
void updateBest()
{
for (int i=1; i<=4; i++)
{
best_ans[i] = curr_ans[i];
}
}

/*
curr_stamp_num:当前的邮票张数
curr_types:当前的邮票类型数
curr_highest:当前的最大面额
start:从第start个类型的邮票开始搜索
curr:当前已选所有邮票的总面额
request:客户输入的面额
*/
void dfs(int curr_stamp_num,int curr_types,int curr_highest,int start,int curr,int request)
{
// 判断是否出现了最优解
if (curr == request)
{
if (max_types < curr_types)
{
max_types = curr_types;
min_stamp_num = curr_stamp_num;
highest_val = curr_highest;
isTie=false;
updateBest();
}
else if (max_types == curr_types)
{
if (min_stamp_num > curr_stamp_num)
{
min_stamp_num = curr_stamp_num;
highest_val = curr_highest;
isTie=false;
updateBest();
}
else if (min_stamp_num == curr_stamp_num)
{
if (highest_val < curr_highest)
{
highest_val = curr_highest;
isTie=false;
updateBest();
}
else if (highest_val == curr_highest)
{
isTie = true;
}
}
}
return ;
}
// 已四张,返回
if (curr_stamp_num == 4)
{
return;
}
/*
此处为何从start而不是0开始搜索?
1.避免重复,如 1 1 2 同 1 2 1在数值上是相同的
2.更重要的是:从0开始是错误的!
回溯结束时,节点i被置为false,那么搜索i+1时如果仍从0开始搜索,会误认为i未访问过,因此,类型数会误加1
*/
for (int i=start; i<stamp_num; i++)
{
if (stamp_val[i] >0 && curr+stamp_val[i] <= request)
{
curr_ans[curr_stamp_num+1]=stamp_val[i];
if (visited[i])
{
visited[i] = true;
dfs(curr_stamp_num+1,curr_types,stamp_val[i],i,curr+stamp_val[i],request);
}
else
{
visited[i] = true;
dfs(curr_stamp_num+1,curr_types+1,stamp_val[i],i,curr+stamp_val[i],request);
}
visited[i] = false;
curr_ans[curr_stamp_num+1]=0;
}
}
}

int main()
{
int tmp;
while (scanf("%d",&tmp)!=EOF)
{
int stamp_value;
stamp_num = 1;
int req;
int customer_num = 0;
memset(stamp_val,0,sizeof(int));
memset(request,0,sizeof(int));
memset(best_ans,0,sizeof(int));
memset(curr_ans,0,sizeof(int));
memset(visited,false,sizeof(bool));

stamp_val[0] = tmp;
while (scanf("%d",&stamp_value))
{
if (stamp_value == 0)
{
break;
}
stamp_val[stamp_num++] = stamp_value;
}
while(scanf("%d",&req))
{
if (req == 0)
{
break;
}
request[customer_num++] = req;
}
sort(stamp_val,stamp_val+stamp_num);

for (int i=0; i<customer_num; i++)
{
max_types = 0;
isTie = false;
min_stamp_num = 0;
if (stamp_val[stamp_num-1]*4 >= request[i] && stamp_val[0] <= request[i])
{
dfs(0,0,0,0,0,request[i]);
}
printf("%d ",request[i]);
if (max_types == 0)
{
printf("---- none\n");
}
else if (isTie)
{
printf("(%d): tie\n",max_types);
}
else
{
sort(best_ans,best_ans+5);
printf("(%d):",max_types);
for (int j=1; j<=4; j++)
{
if (best_ans[j] == 0)
{
continue;
}
printf(" %d",best_ans[j]);
}
printf("\n");
}
}
}
}

/*
枚举/暴搜:注意剪枝,如果面值相同的邮票超过5枚,其它的"剪掉"
*/

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <map>
using namespace std;

int cmp(const void* a,const void* b)
{
return (int*)a - (int*)b;
}

struct ANS
{
int types;
int num ;
int max_value ;
int stamps[30];
};

int stamps[100];
int request[100];

// 获取类型数
int get_types(int a, int b, int c, int d)
{
map<int,int> mp;
mp[a]++;
mp[b]++;
mp[c]++;
mp[d]++;
mp.erase(0);
return mp.size();
}

int main()
{
int tmp;
while (scanf("%d",&tmp)!=EOF)
{
int stamp_num,req,stamp_value ;
int customer_num = 1;
memset(stamps,0,sizeof(stamps));
memset(request,0,sizeof(request));
stamps[1] = tmp;
stamp_num = 2;

map<int,int> mp;
mp[tmp]++;
while(scanf("%d",&stamp_value))
{
if (stamp_value == 0)
{
break;
}
mp[stamp_value]++;
// if the number of the stamps which have the same value is more than 5,then do not put it into stamps arrays.
if (mp[stamp_value] < 6)
{
stamps[stamp_num++] = stamp_value;
}
}
while(scanf("%d",&req))
{
if (req == 0)
{
break;
}
request[customer_num++] = req;
}
qsort(stamps,stamp_num,sizeof(int),cmp);

// for each person
int curr;
for (int i=1; i<customer_num; i++)
{
// curr = 0;
ANS tmp_ans;
ANS best_ans = {0,0,0,{0,0,0,0,0}};
bool tier = false;
// the fist stamp
for (int j=0; j<stamp_num; j++)
{
// the second stamp
for (int k=j; k<stamp_num; k++)
{
// the third stamp
for (int l=k; l<stamp_num; l++)
{
// the forth stamp
for (int m=l; m<stamp_num; m++)
{
curr = stamps[j] + stamps[k] + stamps[l] + stamps[m];
if (curr > request[i])
{
break;
}
else if (curr == request[i])
{
tmp_ans.max_value = max(max(stamps[j],stamps[k]),max(stamps[l],stamps[m]));
tmp_ans.types = get_types(j,k,l,m);

int cnt=1;
if (stamps[j] != 0)
{
tmp_ans.stamps[cnt++] = stamps[j];
}
if (stamps[k] != 0)
{
tmp_ans.stamps[cnt++] = stamps[k];
}
if (stamps[l] != 0)
{
tmp_ans.stamps[cnt++] = stamps[l];
}
if (stamps[m] != 0)
{
tmp_ans.stamps[cnt++] = stamps[m];
}
tmp_ans.num = cnt-1;

// compare the tmp answer with the current best answer
bool flag = false;
if (tmp_ans.types > best_ans.types)
{
flag = true;
tier = false;
}
else if (tmp_ans.types == best_ans.types)
{
if (tmp_ans.num < best_ans.num)
{
flag = true;
tier = false;
}
else if (tmp_ans.num == best_ans.num)
{
if (tmp_ans.max_value > best_ans.max_value)
{
flag = true;
tier = false;
}
else if (tmp_ans.max_value == best_ans.max_value)
{
tier = true;
}
}
}

// update the best answer
if (flag)
{
best_ans.num = tmp_ans.num;
best_ans.types = tmp_ans.types;
best_ans.max_value = tmp_ans.max_value;
for (int ii=1; ii<=best_ans.num; ii++)
{
best_ans.stamps[ii] = tmp_ans.stamps[ii];
}
}
}
}
}
}
}
// output the answer
printf("%d ",request[i]);
if (best_ans.num == 0)
{
printf("---- none\n");
}
else if (tier)
{
printf("(%d): tie\n",best_ans.types);
}
else
{
sort(best_ans.stamps,best_ans.stamps+5);
printf("(%d):",best_ans.types);
for (int j=1; j<=4; j++)
{
if (best_ans.stamps[j] == 0)
{
continue;
}
printf(" %d",best_ans.stamps[j]);
}
printf("\n");
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj