划分大理石(多重背包)

前言

发现自己思路好像和正常人不一样
遂有此篇博客

划分大理石

问题描述

有价值分别为 1..6 的大理石各 a[1..6] 块,现要将它们分成两部分,使得两部分价值之和相等,问是否可以实现。

其中大理石的总数不超过 20000

输入格式:

输入包含多组数据!

每组数据占一行,包含 6 个整数,表示 a[1]a[6]

当输入为 0 0 0 0 0 0 时表示输入结束,且该行无需考虑。

输出格式:

每组数据输出一个结果,每个结果占一行。

如果可以实现则输出 Can,否则输出 Cant

样例输入:

4 7 4 5 9 1
9 8 1 7 2 4
6 6 8 5 9 2
1 6 6 1 0 7
5 9 3 8 8 4
0 0 0 0 0 0

样例输出:

Can't
Can
Can't
Can't
Can

分析

很显然啊,多重背包,而且不问你方案,这就很nice
板子是这样的

bool f[10005];
memset(f,0,sizeof);
f[0]=1;
for (int i=1;i<=6;++i)
    for (int j=1;j<=a[i];++j)
        for (int k=m;k>=a[i];--k)
            f[k]|=f[k-a[i]];
if (f[sum/2]) ...;
else ...;

显然会 TLE Time Limit Enough

考虑优化

考虑到若前i种石头能凑出sum/2,只有两种情况:

  1. i之前, 就已经f[j]=true
  2. i之前, 就已经f[ji]=true

于是考虑贪心

vis[j] 表示 f[j] 在阶段 i 是为 true 的情况下至少需要多少块 i 种石头

则板子的 for(j)for(k) 循环可以优化1维,直接正序扫面

!f[j]&&f[ji]&&vis[ji]a[i] 才可以转移

于是开心的提交

TLE

为啥呢 被hack了

考虑剪枝

发现如果每个价值的大理石都是 2 的倍数,那么必能分成两部分价值相等 (感谢oistars提供的想法)

于是AC了

code

Elaina's code
#include<bits/stdc++.h>
using namespace std;
const int N=150000;
#define rd read()
#define int long long
#define inf 0x3f
#define INF 0x3f3f3f3f
#define mst(a,b) memset(a,b,sizeof(a))
#define re register
#define Elaina 0
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
int n,m,a[8],sum,hsum,f[N],vis[N];

main(){
	#ifdef ONLINE_JUDGE
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	#endif
	
	while(1){
		sum=0;
		for(int i=1;i<=6;++i){
			a[i]=rd;
		}
		if(!a[1]&&!a[2]&&!a[3]&&!a[4]&&!a[5]&&!a[6]) break;
		sum=a[1]%2+a[2]%2+a[3]%2+a[4]%2+a[5]%2+a[6]%2;
		if(!sum){
			printf("Can\n");
			continue;
		}
		sum=a[1]+a[2]*2+a[3]*3+a[4]*4+a[5]*5+a[6]*6;
		if(sum%2){
			printf("Can't\n");
			continue;
		}
        mst(f,0);
		f[0]=1;
		hsum=sum/2;
		for(int i=1;i<=6;++i){
			mst(vis,0);
			for(int j=0;j<=hsum;++j){
				if(f[j]&&!f[j+i]&&vis[j]<a[i]){
					f[j+i]=1;
					vis[j+i]=vis[j]+1;
				}
			}
		}
		if(f[hsum]) printf("Can\n");
		else printf("Can't\n");
	}
	return Elaina;
} 

别急,还有后续

又双叒叕被卡了

都看到这了,真的不点个赞吗(>ω<*)

posted @   Elaina_0  阅读(49)  评论(12编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示