杭电 HDU 2660 Accepted Necklace

http://acm.hdu.edu.cn/showproblem.php?pid=2660

Accepted Necklace

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2220    Accepted Submission(s): 865


Problem Description
I have N precious stones, and plan to use K of them to make a necklace for my mother, but she won't accept a necklace which is too heavy. Given the value and the weight of each precious stone, please help me find out the most valuable necklace my mother will accept.
 

Input
The first line of input is the number of cases. 
For each case, the first line contains two integers N (N <= 20), the total number of stones, and K (K <= N), the exact number of stones to make a necklace. 
Then N lines follow, each containing two integers: a (a<=1000), representing the value of each precious stone, and b (b<=1000), its weight. 
The last line of each case contains an integer W, the maximum weight my mother will accept, W <= 1000. 
 

Output
For each case, output the highest possible value of the necklace.
 

Sample Input
  
  
1 2 1 1 1 1 1 3
 

Sample Output
  
  
1
 


这个题我用的深搜,注意剪枝,特别是要防止重复的出现,比如:2->3->5->6,和3->2->5->6,等。由于是深搜,所以当你再第一块宝石进行比较时会把所有与它有关的可能全部找出来,当它不满足时,后面的搜索就不需要在有第一块宝石了。

这个题感觉也可以用贪心。可先按价值重量比(如果相同则按价值)从大到小排序,然后取前k个(注意判断重量和)。没做出来。

深搜AC代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;

struct Node
{
    int value,weight;
    int yn;
};

Node st[22];
int number;     //最大价值时用的宝石数量
int maxvalue;   //最大价值
int n,k,maxweight;

void Dfs(int nowweight, int mu, int nowvalue, int start)
{
    int nextweight,nextvalue;
    int i;
    if(mu > k)  //剪枝,把宝石数超过需要的删掉
    {
        return ;
    }
    if(nowweight > maxweight) //重量大的剪掉
    {
        return ;
    }
//    printf("nowvalue:%d nowweight:%d mu:%d start:%d maxvalue:%d\n",nowvalue,nowweight,mu,start,maxvalue);
    if(mu == k && nowweight <= maxweight)
    {
        if(nowvalue > maxvalue)
        {
            maxvalue = nowvalue;
        }
        return ;
    }
    for(i = start; i < n; i++)  //从start开始,由于上一个递归已经把前面的全部已经考虑了,防止重复考虑
    {
        nextweight = nowweight + st[i].weight;
        nextvalue = nowvalue + st[i].value;
        if(st[i].yn == 0)
        {
            st[i].yn = 1;    //标记此宝石已经用了
            Dfs(nextweight,mu+1,nextvalue,i+1);
            st[i].yn = 0;
        }
    }
    return ;
}

int main()
{
    int t,i,num,nowvalue,mu,nowweight;
    int start;
    scanf("%d",&t);
    while(t--)
    {
        maxvalue = nowvalue = 0;    //最高价值和当前价值清零
        nowweight = number = 0;     //当前重量和所用宝石数量清零
        start = mu = 0;                  //从第下标为0的第一个宝石开始搜索
        scanf("%d%d",&n,&k);
        for(i = 0; i < n; i++)
        {
            scanf("%d%d",&st[i].value,&st[i].weight);
            st[i].yn = 0;
        }
        scanf("%d",&maxweight);
        Dfs(nowweight,mu,nowvalue,start);
        printf("%d\n",maxvalue);
    }

    return 0;
}


贪心写的,但是 没有AC的代码,不知道原因。可能有些情况没有考虑到。。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

struct Node
{
    int value,weight;
    double yn;
};

Node st[22];

bool cmp(Node a, Node b)
{
    if(a.yn == b.yn)
    {
        return a.value > b.value;
    }
    return a.yn > b.yn;
}

int main()
{
    int t,n,k,i,weight,nub,maxweight;
    int sum;
    scanf("%d",&t);
    while(t--)
    {
        weight = nub = sum = 0;
        scanf("%d%d",&n,&k);
        for(i = 0; i < n; i++)
        {
            scanf("%d%d",&st[i].value,&st[i].weight);
            st[i].yn = ((double)st[i].value)/((double)st[i].weight);
        }
        scanf("%d",&maxweight);
        sort(st,st+n,cmp); //按价值重量比和价值排序
        for(i = 0; i < n; i++)
        {
            if(weight+st[i].weight <= maxweight && nub < k)
            {
                sum = sum + st[i].value;
                weight = weight + st[i].weight;
                nub++;   //满足条件宝石数加一
            }
            else
            {
                break;
            }
        }
        printf("%d\n",sum);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值