糯米

TI DaVinci, gstreamer, ffmpeg
随笔 - 167, 文章 - 0, 评论 - 47, 引用 - 0
数据加载中……

POJ 3040 Allowance 贪心

思路:

每次放钱的时候,遵循两个原则来寻找最优方案:
1. 不能用面额小的组成面额大的
2. 所有方案中取最接近 C 的那个
就这样一次次的放,放到没钱为止。

注意,由于货币的数量较大,如果最优方案可以执行多次,那就一次过执行完。

#include <stdio.h>
#include 
<stdlib.h>

#define MAX_N 64

struct node {
    
int val, cnt;
}
;
struct node coin[MAX_N];
int N, C, best, best_idx, ans, need[MAX_N];

inline 
int min(int a, int b)
{
    
return a < b ? a : b;
}


int cmp(const void *a, const void *b)
{
    
return ((struct node *)a)->val - ((struct node *)b)->val;
}


inline 
int put(int idx, int val)
{
    
int n;

    n 
= min(coin[idx].cnt, (C - val - 1/ coin[idx].val);
    val 
+= coin[idx].val * n;
    
if (coin[idx].cnt > n) {
        
if (!best || val + coin[idx].val < best) {
            best 
= val + coin[idx].val;
            best_idx 
= idx;
        }

    }
 
    need[idx] 
= n;

    
return val;
}


inline 
int can()
{
    
int i, val;

    best 
= val = 0;
    
for (i = N - 1; i >= 0; i--)
        val 
= put(i, val);

    
return best;
}


inline 
void update()
{
    
int i, cnt;

    cnt 
= 100000000;
    need[best_idx]
++;
    
for (i = N - 1; i >= best_idx; i--)
        
if (need[i])
            cnt 
= min(cnt, coin[i].cnt / need[i]);
    
for (i = N - 1; i >= best_idx; i--
        coin[i].cnt 
-= cnt * need[i];
    ans 
+= cnt;
}


int main()
{
    
int i;

    scanf(
"%d%d"&N, &C);
    
for (i = 0; i < N; i++
        scanf(
"%d%d"&coin[i].val, &coin[i].cnt);
    qsort(coin, N, 
sizeof(coin[0]), cmp);
    
    
while (coin[N - 1].val >= C) {
        ans 
+= coin[N - 1].cnt;
        N
--;
    }

    
while (can())
        update();
    
    printf(
"%d\n", ans);

    
return 0;
}

posted on 2010-04-13 12:25 糯米 阅读(548) 评论(0)  编辑 收藏 引用 所属分类: POJ


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理