01背包问题(动态规划)

题目描述
PIPI有一台笔记本电脑,一台台式机电脑,两台电脑的性能相同,现在小明手里有N个等待运行的程序,每个程序运行所需的时间分别为n1,n2,n3,n4……,一台电脑同一时刻只能运行一个程序,一个程序只需要运行一次。两台电脑同时开始运行,请问小明该如何分配程序在这两台电脑上运行,使得最后结束运行的电脑的运行时间最短。
输入
输入不超过30组数据,每组数据第一行为N,代表有N个等待运行的程序,第二行为N个数字,代表每个程序的运行时间,1 <= N <= 1000 ,每个程序的运行时间均为正整数, 所有程序的运行时间之和不超过5000。
输出
输出最后结束运行的电脑的运行时间。
样例输入

2
1 1
2
1 2
3
1 2 3

样例输出

1
2
3

贪心不行,是01背包问题
即只有一台电脑时依次运行需要运行的时间的一半,最多可以运行多长
总数减去一半最多耗时,即答案,另一台电脑需要的最长时间
01背包问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int N;
int arr[1005];
int sum,mid;
int dp[1005][2510];
int main(){
    int i,j;
while(scanf("%d",&N)!=EOF){
    sum=0;
    memset(dp,-1,sizeof(dp));
    for(i=1;i<=N;i++){
        scanf("%d",&arr[i]);
        sum+=arr[i];
        dp[i][0]=0;
        }
    dp[0][0]=0;
    mid=sum/2;
    for(i=1;i<=mid;i++)dp[0][i]=0;
    for(i=1;i<=N;i++)
        for(j=1;j<=mid;j++)
        if(j<arr[i]) dp[i][j]=dp[i-1][j];
        else dp[i][j]=max(dp[i-1][j],dp[i-1][j-arr[i]]+arr[i]);


    printf("%d\n",sum-dp[N][mid]);
}//while
return 0;
}

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[1005],dp[5005];
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        memset(dp,0,sizeof(dp));
        int sum=0;
        for(int i=0;i<n;i++) scanf("%d",&a[i]),sum+=a[i];
        int ans=sum;
        sum/=2;
        sort(a,a+n);
        dp[0]=1;
        for(int i=0;i<n;i++)
            for(int j=sum;j>=a[i];j--)
                if(dp[j-a[i]]) dp[j]=1;
        for(int i=sum;;i--)
        if(dp[i]) {printf("%d\n",ans-i);break;}
    }
}

1076: 饭卡

题目描述
CSU本部食堂的饭卡有一种很诡异的设计——在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
输入
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
输出
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
样例输入

1
50
5
10
1 2 3 2 1 1 2 3 2 1
50

样例输出

-45
32

把最贵的菜留五块钱最后买即可使余额最少
即转化为money-5的从1到n-1中选择的01背包问题
要注意的是,如果money<5,则直接输出money(因为什么也买不了ovO)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
int cmp(const void *a,const void *b){
return (*(int*)a-*(int*)b);
}
int N;
int cost[1005];
int dp[1005][1005];
int money;
int main(){
    int i,j;
    while(scanf("%d",&N)!=EOF){
        for(i=1;i<=N;i++)
            scanf("%d",&cost[i]);
        scanf("%d",&money);
        if(money<5) {printf("%d\n",money);continue;}
        qsort(cost+1,N,sizeof(int),cmp);
        money-=5;
        for(i=0;i<N;i++) dp[i][0]=0;
        for(i=1;i<=money;i++)dp[0][i]=0;
        for(i=1;i<N;i++)
            for(j=1;j<=money;j++)
            if(j<cost[i]) dp[i][j]=dp[i-1][j];
           else dp[i][j]=max(dp[i-1][j],dp[i-1][j-cost[i]]+cost[i]);
     printf("%d\n",money+5-dp[N-1][money]-cost[N]);
    }

return 0;
}

1079

#include <stdio.h>
#include <string.h>
int n,m,val[500],wei[500];
int dp[10005];
int main(){
    int i,j;
while(scanf("%d %d",&n,&m)!=EOF){
    for(i=0;i<n;i++)
        scanf("%d %d",&val[i],&wei[i]);
    memset(dp,0,sizeof(dp));
    for(i=0;i<n;i++)
    for(j=wei[i];j<=m;j++)
    if(dp[j-wei[i]]||j==wei[i])  if(dp[j]==0||dp[j]>dp[j-wei[i]]+val[i]) dp[j]=dp[j-wei[i]]+val[i];
    if(dp[m]==0) printf("impossible\n");
    else printf("%d\n",dp[m]);
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值