DP

 数塔问题

for(i=0;i<N;i++)
		{
			dp[N-1][i]=a[N-1][i];
		}
		for(i=N-2;i>=0;i--)
		{
		    for(j=0;j<=i;j++)
		    {
		    	dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+a[i][j];
			}
		}
		printf("%d\n",dp[0][0]);

母牛的故事

5以后每年都是上一年加上前三年的dp,原来有的加上三年前有的,三年前有的都会在这一年生一个母牛。

for(i=1;i<5;i++)      dp[i]=i;
    for(i=5;i<55;i++)
    {
	     dp[i]=dp[i-1]+dp[i-3];
	} 
} 

超级楼梯

每多上一层楼就等于上一级和上上级,从上级走一步到这级,从上上级走两步到这级。到这级的方法有两种,相加就好。

dp[1]=0;dp[2]=1;dp[3]=2;
    for(i=4;i<41;i++)
    {
	     dp[i]=dp[i-1]+dp[i-2];
	} 

Bone Collector

01背包问题,t种物品,总重最大volu,求最大价值。注意j=0开始!!!还有j>=w[i],其他值记得赋值。

memset(dp,0,sizeof(dp));
		for(i=1;i<=t;i++)
		{
			for(j=0;j<=volu;j++)
			{
				if(j>=w[i])
				{
					dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
				}
				else   dp[i][j]=dp[i-1][j];
			}
		}
		printf("%d\n",dp[t][volu]); 

饭卡

贪心:为了更划算,留下最大的最后买。 剩余的菜用sum-5购买最大价值的。转换为01背包问题,重量和价值都为a[i],最大承重是sum-5。

#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
	int n,i,j,yu,money;
	while(scanf("%d",&n)!=EOF&&n)
	{
	   int a[n+5];
	   for(i=1;i<=n;i++)
	  {
		  scanf("%d",&a[i]);
	  }
	  scanf("%d",&yu);
	  int dp[n+5][yu];	
	  memset(dp,0,sizeof(dp));
	  if(yu<5)
	  {
	  	printf("%d\n",yu);continue;
	  }
	  sort(a+1,a+n+1);
	  money=yu-5;
	  for(i=1;i<n;i++)
		{
			for(j=1;j<=money;j++)
			{
				if(j>=a[i])
				{
					dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);
				}
				else    dp[i][j]=dp[i-1][j];
			}
	   }
	  printf("%d\n",yu-dp[n-1][money]-a[n]);
    }
	return 0;
}

 选修课

多重背包问题,注意j逆取。

memset(dp,0,sizeof(dp));
		dp[0]=1;
		for(i=1;i<=k;i++)
		{
			for(j=n;j>=a[i];j--)
			{
				for(l=1;l<=b[i];l++)
				{
					if(j>=a[i]*l)    dp[j]+=dp[j-a[i]*l];
				}
			}
		}
		printf("%d\n",dp[n]);

Sumsets

1、2的倍数为组合数,问一个数有多少种组合方式?

当这个数为奇数时,即上一个数每个数加一,方法数不变。

为偶数时,即上一个数的方法每个加一,如果加数里没有1,即对n/2的每一个加数式乘以2,总类数为a[n/2]
所以总的种类数为:a[n]=a[n-2]+a[n/2];加一 或者乘二;

a[1]=1;a[2]=2;
	for(i=3;i<1000001;i++)
	{
		if(i%2==0)  a[i]=a[i-2]+a[i/2];
		else  a[i]=a[i-1];
		a[i]=a[i]%1000000000;
	}

命运

一定要注意INF值,特别注意,不能写为-1000,或更小

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=-100;
int dp[25][1005];
int a[25][1005];
int x,y;
int main()
{
	int n,ans;
	scanf("%d",&n);
	while(n--)
	{
		memset(dp, inf, sizeof(dp));
		scanf("%d%d",&x,&y);
		for(int i=1;i<=x;i++)
		{
			for(int j=1;j<=y;j++)
			{
				scanf("%d",&a[i][j]);
			}
		}
		for(int i=0;i<=x;i++)
		{
			for(int j=0;j<=y;j++)
			{
				if(i==0||j==0)  dp[i][j]=0;
				ans=inf;
				ans=max(dp[i-1][j],dp[i][j-1]);
				for(int k=1;k<j;k++)
				{
					if(j%k==0)   ans=max(ans,dp[i][k]);
				}
				dp[i][j]=ans+a[i][j];
			}
		}
		printf("%d\n",dp[x][y]);
	}
	return 0;
 }

二进制处理多重背包问题

Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One day Hibix opened purse and found there were some coins. He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch.


You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.

Input

The input contains several test cases. The first line of each test case contains two integers n(1 ≤ n ≤ 100),m(m ≤ 100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1 ≤ Ai ≤ 100000,1 ≤ Ci ≤ 1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

Sample Output

8
4

数组a是每个商品的价值,数组c是每个商品的数量。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
int a[105],b[105],c[100005],dp[100005];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<n;i++)
            scanf("%d",&b[i]);
        int k=0;
        for(int i=0;i<n;i++)
        {
            for(int j=1;j<=b[i];j<<=1)
            {
                c[k++]=a[i]*j;
                b[i]-=j;
            }
            if(b[i]>0)
            {
                c[k++]=a[i]*b[i];
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<k;i++)
        {
            for(int j=m;j>=c[i];j--)
            {
                dp[j]=max(dp[j],dp[j-c[i]]+c[i]);
            }
        }
        int cnt=0;
        for(int i=1;i<=m;i++)
        {
            if(dp[i]==i){
                cnt++;
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}

 另一种方法:判断是否能组成这个数,增加一个一维数组num[ j ],记录到达j元时i种钱用的次数。每多一种硬币种类,重新赋值num[ j ] 为0。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
int a[105],b[105];
int dp[100005],num[100005];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
    {
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i]);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=m;j++)
                num[j]=0;
            for(int j=a[i];j<=m;j++)
            {
                if(!dp[j]&&dp[j-a[i]]&&num[j-a[i]]<b[i])
                {
                    dp[j]=1;
                    num[j]=num[j-a[i]]+1;
                }
            }
        }
        int cnt=0;
        for(int i=1;i<=m;i++)
        {
            if(dp[i])
                cnt++;
            //printf("%d ",dp[i]);
        }
        printf("%d\n",cnt);
    }
}

Problem Description

Marsha and Bill own a collection of marbles. They want to split the collection among themselves so that both receive an equal share of the marbles. This would be easy if all the marbles had the same value, because then they could just split the collection in half. But unfortunately, some of the marbles are larger, or more beautiful than others. So, Marsha and Bill start by assigning a value, a natural number between one and six, to each marble. Now they want to divide the marbles so that each of them gets the same total value.
Unfortunately, they realize that it might be impossible to divide the marbles in this way (even if the total value of all marbles is even). For example, if there are one marble of value 1, one of value 3 and two of value 4, then they cannot be split into sets of equal value. So, they ask you to write a program that checks whether there is a fair partition of the marbles.

Input

Each line in the input describes one collection of marbles to be divided. The lines consist of six non-negative integers n1, n2, ..., n6, where ni is the number of marbles of value i. So, the example from above would be described by the input-line ``1 0 1 2 0 0''. The maximum total number of marbles will be 20000.

The last line of the input file will be ``0 0 0 0 0 0''; do not process this line.

Output

For each colletcion, output ``Collection #k:'', where k is the number of the test case, and then either ``Can be divided.'' or ``Can't be divided.''.
Output a blank line after each test case.

Sample Input

1 0 1 2 0 0 1 0 0 0 1 1 0 0 0 0 0 0

Sample Output

Collection #1: Can't be divided. Collection #2: Can be divided.

给出六个数字,每个商品的价值就是位置坐标大小,每个商品的数量是该位置的值。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=20005;
const int maxm=120010;
int dp[maxm];
int b[maxn];
int main()
{
    int a[8];
    int cas=1;
    while(1)
    {
        int sum=0,k=1;
        memset(a,0,sizeof(a));
        for(int i=1;i<=6;i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i]*i;
            for(int j=1;j<=a[i];j<<=1)
            {
                b[k++]=i*j;
                a[i]-=j;
            }
            if(a[i]>0)
                b[k++]=a[i]*i;
        }
        if(sum==0) return 0;
        printf("Collection #%d:\n",cas++);
        if(sum%2==1)
        {
            printf("Can't be divided.\n\n");
            continue;
        }
        else
        {
            sum/=2;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<k;i++)
            {
                for(int j=sum;j>=b[i];j--)
                {
                    dp[j]=max(dp[j],dp[j-b[i]]+b[i]);
                }
            }
            if(dp[sum]==sum) printf("Can be divided.\n");
            else    printf("Can't be divided.\n");
            printf("\n");
        }
    }
    return 0;
}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值