divide(有趣DP)

divide
【问题描述】
小Y 和他的MM 有一个共同爱好——打弹珠。但是小Y 也遇到了困惑,他和MM 没有办法把
他们拥有的弹珠怎么两人平分! 但是简单的数量上的平分没有办法满足MM 的好胜心。MM 要他
们两人拥有的弹珠价格上相等才算是公平竞争!
现在告诉你每种价格的弹珠的个数= =!问你能不能把弹珠按照价格平分使得比赛公平!
【输入格式】
出于小Y 很爱他的MM 所以他们拥有很多很多的弹珠!弹珠总价值多达20000!
不过MM 有恋物癖所以他们只拥有6 种弹珠= =||MM 有恋物癖呀有没有!有没有!每种弹珠
的价格是1 2 3 4 5 或者6;
所以输入数据有六个整数n1,n2,n3,n4,n5,n6 表示价格为1 2 3 4 5 或者6 的弹珠的数量
每组测试包含n 组数据在第一行给出
【输出格式】
输出包含一个字符串,如果可以分割那么输出”Can be divided.”,否则输出”Can’t be divided.”
.
【样例输入】
1
1 0 1 2 0 0
【样例输出】
Can’t be divided.

题面:给1,2,3,4,5,6,每个数的个数,问他们能不能对半分

做的时候猜想有没有好的方法可以过大数据,于是猜数论,发现是做梦
老老实实打完全背包。。。
memcmp(f,0,sizeof(0))
因为把初始化f数组写成了以上屁话,这道题就只有八分了哈哈哈

正解
完全背包
f[i]表示达到i这个数时,每个j(1,2,3,4,5,6)还能用多少个
到最后如果f[sum/2]>=0那么就可以

80分代码

#include<bits/stdc++.h>
using namespace std;
int f[200010],n,m,a[10],v[10],w[10];
int main() 
{
	int t;
	scanf("%d",&t);
	while (t--)
	  {
	  	int sum=0;
	  	memset(f,0,sizeof(f));
	  	for (int i=1; i<=6; i++)
	  	{
	  	  scanf("%d",&a[i]);
	      w[i]=i;
	      v[i]=i;
	      sum+=a[i]*i;;
		}
		f[0]=1;
	  	for(int i=1;i<=6;i++)
         for(int j=sum/2;j>=0;j--)
            for(int k=0;k<=a[i];k++)
               if(j-k*v[i]>=0&&f[j-k*v[i]]!=0)
                 f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);
        if (sum%2!=0) puts("Can't be divided."); 
		else 
	    if (f[sum/2]!=0) puts("Can be divided."); 
		else puts("Can't be divided.");
	  }
}

AC

#include<bits/stdc++.h>
#define rep(i,j,k) for((i)=(j);(i)<=(k);++i)
using namespace std;
int T,s,i,j,a[10],f[20005];
int inline read(){
	char ch=getchar();int z=0,f=1;
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){z=z*10+ch-'0';ch=getchar();}
	return z*f;
}
int main(){
	freopen("divide.in","r",stdin);
	freopen("divide.out","w",stdout);
	T=read();
	while(T--){
		s=0; rep(i,1,6) a[i]=read(),s+=i*a[i];
		if(s&1){puts("Can't be divided."); continue;}
		s>>=1; f[0]=0; rep(i,1,s) f[i]=-1;
		rep(i,1,6)
			rep(j,0,s)
				if(f[j]>=0) f[j]=a[i];
				else if(i<=j) f[j]=f[j-i]-1; else f[j]=-1;
		if(f[s]>=0) puts("Can be divided."); else puts("Can't be divided.");
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值