您的位置:首页 > 其它

LightOJ 1231+1232+1122+1047 (简单dp)

2013-07-15 11:03 197 查看
LightOJ 1231 Coin Change (I)

题目链接 http://lightoj.com/volume_showproblem.php?problem=1231
题意:给你n个物品的体积和数量,让你求有多少种组合能恰好装满M体积的背包。

思路:最开始想的是多重背包和母函数,发现都不太合适。最后还是回归最基本的dp吧。

dp[i][j]表示前i种物品,组成j的容量有几种取法,枚举第i种物品取得数量,注意可以不取。

#include <cstdio>
#include <cstring>

int n,sum,v;
int dp[55][1005],c[55],num[55];

const int mod=100000007;

int main ()
{
    int T;
    scanf("%d",&T);
    for (int Cas=1;Cas<=T;Cas++)
    {
		int i;
		scanf("%d%d",&n,&v);
		sum=0;
		memset(dp,0,sizeof(dp));
		for (i=1;i<=n;i++)
			scanf("%d",&c[i]);
		for (i=1;i<=n;i++)
			scanf("%d",&num[i]);

		for (int ss=1;ss<=n;ss++)
			for (i=1;i<=num[ss];i++)
				if (i*c[ss]<=v)
					dp[ss][i*c[ss]]=1;

		for (i=2;i<=n;i++)
			for (int j=1;j<=v;j++)
				for (int k=0;k<=num[i];k++)
					if (j-k*c[i]>0)
						dp[i][j]=(dp[i][j]%mod+dp[i-1][j-k*c[i]]%mod)%mod;
		printf("Case %d: %d\n",Cas,dp
[v]%mod);
	}
	return 0;
}


优化后的代码,效率提高很多:

#include <cstdio>
#include <cstring>
 
int n,v;
int dp[55][1005],c[55],num[55];
 
const int mod=100000007;
 
int main ()
{
    int T,i;
    scanf("%d",&T);
    for (int Cas=1;Cas<=T;Cas++)
    {
        scanf("%d%d",&n,&v);
        memset(dp,0,sizeof(dp));
        for (i=1;i<=n;i++)
            scanf("%d",&c[i]);
        for (i=1;i<=n;i++)
            scanf("%d",&num[i]);
        dp[0][0]=1;
        for (i=1;i<=n;i++)
            for (int j=0;j<=v;j++)
                for (int k=0;j+k*c[i]<=v && k<=num[i];k++)
                {
                    dp[i][j+k*c[i]]+=dp[i-1][j];
                    dp[i][j+k*c[i]]%=mod;
                }
        printf("Case %d: %d\n",Cas,dp
[v]%mod);
    }
    return 0;
}


LightOJ 1231 Coin Change (II)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1232

题意:和上面那道差不多,只是每个最多只能用k次,看起来很麻烦,但其实就是最水的完全背包……

#include <cstdio>
#include <cstring>
#define max(x,y) ((x)>(y)?(x):(y))

const int mod=100000007;
int w[105],dp[100005];
int n,v;

void CompletePack ()
{
	int i,j;
	memset(dp,0,sizeof(dp));
	dp[0]=1;
	for (i=1;i<=n;i++)
		for (j=w[i];j<=v;j++)
			dp[j]=(dp[j]+dp[j-w[i]])%mod;
}

int main ()
{
	int T;
	scanf("%d",&T);
	for (int Cas=1;Cas<=T;Cas++)
	{
		scanf("%d%d",&n,&v);
		for (int i=1;i<=n;i++)
			scanf("%d",&w[i]);
		CompletePack ();
		printf("Case %d: %d\n",Cas,dp[v]);
	}
	return 0;
}


LightOJ 1122 Digit Count

题意:给出数字集合S,求由S中元素构成长度为N且相邻位数字只差不超过2的数字有几个。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
  
int dp[12][12]; //dp[i][j] 表示长度为i 以数字data[j]结尾的方案数
int data[12];
  
int main ()
{  
#ifdef ONLINE_JUDGE
#else
	freopen("read.txt","r",stdin);
#endif
	int T,n,m;
	scanf("%d",&T);
	for (int Cas=1;Cas<=T;Cas++)
	{
		printf("Case %d: ",Cas);
		memset(dp,0,sizeof(dp));
		scanf("%d%d",&m,&n);
		int i;
		for (i=1;i<=m;i++)
			scanf("%d",&data[i]);

		for (i=1;i<=m;i++)
			dp[1][i]=1;
		for (i=2;i<=n;i++)
			for (int j=1;j<=m;j++)
				for (int k=1;k<=m;k++)
					if (abs(data[k]-data[j])<=2)
						dp[i][j]+=dp[i-1][k];
		int ans=0;
		for (i=1;i<=m;i++)
			ans+=dp
[i];
		printf("%d\n",ans);
	}
	return 0;
}


Lightoj 1047 Neighbor House

题意:有n户人,打算把他们的房子图上颜色,有red、green、blue三种颜色,每家人涂不同的颜色要花不同的费用,而且相邻两户人家之间的颜色要不同,求最小的总花费费用

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
#define min3(a,b,c) min((a),min((b),(c)))

int data[25][4];
int dp[25][4];//dp[i][j]第i户选j时的最小钱数

int main ()
{  
#ifdef ONLINE_JUDGE
#else
	freopen("read.txt","r",stdin);
#endif
	int T;
	scanf("%d",&T);
	for (int Cas=1;Cas<=T;Cas++)
	{
		int i,n,a,b;
		scanf("%d",&n);
		for (i=1;i<=n;i++)
			scanf("%d%d%d",&data[i][1],&data[i][2],&data[i][3]);
		memset(dp,0,sizeof(dp));
		for (i=1;i<=3;i++)
			dp[1][i]=data[1][i];
		for (i=2;i<=n;i++)
			for (int j=1;j<=3;j++)
			{
				if (j==1) a=2,b=3;
				if (j==2) a=1,b=3;
				if (j==3) a=2,b=1;
 				dp[i][j]=data[i][j]+min(dp[i-1][a],dp[i-1][b]);
//				printf("%d %d %d\n",j,a,b);
			}
		int ans=min3(dp
[1],dp
[2],dp
[3]);
		printf("Case %d: %d\n",Cas,ans);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: