计算机机试指南之动态规划

4.Coincidence问题描述:find a longest common subsequence of two strings.(找到两个字符串的最长公共子序列)输入:first and second line of each input case contain two strings of lowercase character a...z. there are no space
摘要由CSDN通过智能技术生成

4.Coincidence

问题描述:find a longest common subsequence of two strings.(找到两个字符串的最长公共子序列)

输入:first and second line of each input case contain two strings of lowercase character a...z. there are no spaces before, inside or after the strings. length of the strings do not exceed 100.(第一行第二行分别输入两个包含a...z的字符串,不包含空格,字符串长度不超过100)

输出:for each case, output k--the length of a longest common subsequence in one line(每一种情况,输出最长公共子序列 的长度)

//最长公共子序列长度
#include<stdio.h>
#include<string.h>
int buf[101][101];
int max(int a, int b){return a>b?a:b;}
char first[101],second[101];
int main(){
	while(scanf("%s%s",first,second)!=EOF){
		int l1=strlen(first);
		int l2=strlen(second);
		for(int i=0;i<l1;i++)buf[i][0]=0;
		for(int j=0;j<l2;j++)buf[0][j]=0;
		for(int i=1;i<l1;i++){
			for(int j=1;j<l2;j++){
				if(first[i]==second[j])buf[i][j]=buf[i-1][j-1]+1;
				else buf[i][j]=max(buf[i-1][j],buf[i][j-1]);
			}
		}
		printf("最长公共字符串长度为:%d\n",buf[l1-1][l2-1]);
	}
	return 0;
} 

背包问题——0-1背包、完全背包、多重背包
5.采药问题(0-1背包问题:每种草药有两种状态,在背包中;不在背包中)

问题描述:在固定的时间里采一些草药,使得草药的价值最大

输入:输入的第一行有两个整数T(1<=T<=1000)和M(1<=M<=100),T代表总共能够用来采药的时间,M代表山洞里草药的数目。接下来的M行每行包括两个在1到100之间的整数,分别表示采摘某株草药的时间和这株草药的价值。

输出:可能有多组测试数据,对于每组数据,输出只包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

//0-1背包问题
#include<stdio.h>
int buf[101][1001];//总时间不超过j的情况下前i个草药所能达到的最大价值
/*
若第一棵草药所需时间超过总时间则不采,若某一棵草药时间短于剩余时间,则将此草药采下,满足采此草药的时间为当前时间减去采此草药所耗费的时间,
每一个buf表示当前时刻最多可以有多少价值 
*/ 
int max(int a,int b){return a>b?a:b;
} 
int main(){
	int T,M;
	while(scanf("%d%d",&T,&M)!=EOF){
		int time[101],value[101];
		for(int i=1;i<=M;i++){
			scanf("%d%d",&time[i],&value[i]);
		}
		for(int j=0;j<=T;j++){
			buf[0][j]=0;
		} 
		for(int i=1;i<=M;i++){
			for(int j=T;j>=time[i];j--){//j表示当前时刻,要保证还剩余的时间大于第i个草药所耗费的时间 
				buf[i][j]=max(buf[i-1][j-time[i]]+value[i],buf[i-1][j]);//若第i个草药在背包中,原所用时间不超过j-time[i] ,新价值加上第i个草药的价值;
				//若第i个草药不在背包中,原所用时间不超过j 
			}
			for(int j=time[i]-1;j>=0;j--){
				buf[i][j]=buf[i-1][j];
			} 
		}
		printf("草药最大价值为:%d",buf[M][T]); 
	}
	return 0;
} 
输入:70 3\n71 100\n69 1\n1 2\n
输出:3
0-1背包问题
buf0123...686970
000000000
100000000
201111111
301233333

若用一维数组表示前i种状态的最大价值,则状态转移函数为:buf[j]=max{buf[j-time[i]]+value[i],buf[j]}

//0-1背包问题
#include<stdio.h>
int buf[1001];//总时间不超过j的情况下前i个草药所能达到的最大价值
/*
若第一棵草药所需时间超过总时间则不采,若某一棵草药时间短于剩余时间,则将此草药采下,满足采此草药的时间为当前时间减去采此草药所耗费的时间,
每一个buf表示当前时刻最多可以有多少价值 
*/ 
int max(int a,int b){return a>b?a:b;
} 
int main(){
	int T,M;
	while(scanf("%d%d",&T,&M)!=EOF){
		int time[101],value[101];
		for(int i=1;i<=M;i++){
			scanf("%d%d",&time[i],&value[i]);
		}
		for(int j=0;j<=T;j++){
			buf[j]=0;
		} 
		for(int i=1;i<=M;i++){
			for(int j=T;j>=time[i];j--){//j表示当前时刻,要保证还剩余的时间大于第i个草药所耗费的时间 
				buf[j]=max(buf[j-time[i]]+value[i],buf[j]);//若第i个草药在背包中,原所用时间不超过j-time[i] ,新价值加上第i个草药的价值;
				//若第i个草药不在背包中,原所用时间不超过j 
			}
			} 
		printf("草药最大价值为:%d",buf[T]); 	
		}
	return 0;
} 


6.Piggy-Bank(完全背包:要求所选择的物品必须恰好装满背包)

问题描述:there is a piggy-bank, but it is not possible to determine how much money is inside. the only way is to weigh the piggy-bank and try to guess how many coins are inside. we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. then there is some minimum amount of money in the piggy-bank that we can guarantee. find out the minimum amount of cash inside the piggy-bank.

输入:the input consists of T test cases. the number of them is given on the first line of the input file. each test case begins with a line containing two integers E and F. they indicate the weight of an empty pig and of the pig filled with coins. both weights are given in grams. no pig weigh more than 10kg, that means 1<=E<=F<=10000. on the second line of each test case, there is an integer number N(1<=N<=500) that gives the number of various coins used in the given currency. Following this are exactly N lines, each one coin type. these lines contain two integers each, P and W(1<=P<=50000,1<=W<=10000).P is the value of the coin in monetary unit, W is weight in grams.

输出:one line of output for each test case. the line must contain the minimum amount of money.

//完全背包问题
#include<stdio.h>
#define INF 0x7fffffff 
int min(int a,int b){return a<b?a:b;}
struct E{
	int value;
	int weight;
}CoinType[501];
int buf[10001];//状态 
int main(){
	int T;//number of cases
	scanf("%d",&T);
	while(T--){
		int E,F;//1<=E<=F<=10000,w eight of empty and filled with coins
		scanf("%d%d",&E,&F);
		F=F-E;//硬币的总重量 
		int n;//number of coin types
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d%d",&CoinType[i].value,&CoinType[i].weight);
		}
		for(int i=0;i<=F;i++){
			buf[i]=INF;//为每一种状态赋初值 
		}
		buf[0]=0;
		for(int i=1;i<=n;i++){
			for(int j=CoinType[i].weight;j<=F;j++){//一枚该硬币的重量为cointype[i].weight,每次增加一枚硬币都要保证 
				if(buf[j-CoinType[i].weight]!=INF){
					buf[j]=min(buf[j],buf[j-CoinType[i].weight]+CoinType[i].value);//前一个状态加上一枚第i硬币和原有值得最小值 
				}
			}
		}
		if(buf[F]!=INF){
			printf("the minimum amount of money in the piggy-bank is %d.\n",buf[F]);
		}
		else puts("this is impossible");	 
	}
	return 0;
} 
7.有限资金采购粮食问题(多重背包问题,每种物品的数量为k)

问题描述:一共有资金n元,市场有m种大米,每种大米都是袋装产品,价格不等,并且只能整袋购买,请问用有限的资金最多能够采购多少公斤粮食?

输入:输入数据首先包含一个正整数c,表示有c组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100,1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量和对应种类大米的袋数

输出:对于每组测试数据,请输出能够购买大米的最多重量。可以假设经费买不光多有大米,并且经费可以用不完,每个实例输出一行。

//多重背包问题
#include<stdio.h>
struct E{
	int w;//price of rice
	int v;//weight of rice 
}list[2001];
int dp[101];
int max(int a,int b){
	return a>b?a:b;
} 
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int s,n;
		scanf("%d%d",&s,&n);
		int cnt=0;//拆分后物品总数 
		for(int i=1;i<=n;i++){
			int v,w,k;
			scanf("%d%d%d",&w,&v,&k);
			int c=1;
			while(k-c>0){
				k-=c;
				list[++cnt].w=c*w;
				list[cnt].v=c*v;
				c*=2;
			}
			list[++cnt].w=w*k;
			list[cnt].v=v*k;
		} 
		for(int i=1;i<=s;i++)dp[i]=0;
		for(int i=1;i<=cnt;i++){
			for(int j=s;j>=list[i].w;j--){
				dp[j]=max(dp[j],dp[j-list[i].w]+list[i].v);
			}
		}
		printf("%d\n",dp[s]);
	}
	return 0;
}
多重背包问题介于0-1背包和完全背包之间:有容积为v的背包,给定一些物品,每种物品包含体积w、价值v和数量k,求背包能够装下的最大价值总量。将多重背包问题转换成0-1背包问题,普通转换可能会超时,这里利用二进制转换,每组物品包含的原物品个数分别为1、2、4、8...k-2^c+1,其中c为使 k-2^c+1大于0的最大整数













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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值