Time Limit Exceeded
直接DFS暴搜.....死的很安详,然后写了母函数的解法,死的也很安详超时(:逃 江湖传言 sum取模60可AC多重背解未被AC
关于多重背包的解法不想说啥,这里就是将承重m换成了价值v来理解筛选,用价值V来刷选最大可以筛选出Vmax及dp[V]=V,如果不等说明这个价值不可以被组合选举出来,其中多重背包二进制转化01背包也有很详细的讲解...
如果不懂可以看我的自学笔记关于背包问题的,我从不会到会的所有理解,非常详细......
(:机票 https://blog.csdn.net/QingCoffe/article/details/85239055 如果你不会01背包问题,我想你看完的收益会很大
01/多重/完全/背包问题等 (:逃
多重背包解法:(没被AC搞不懂为啥,用可AC代码自检,发现代码输出结果没问题.....不知道哪里出了问题懒得搞了)
# include<iostream>
# include<algorithm>
#pragma warning (disable:4996)
using namespace std;
int n[6];
int val[20010],dp[60020];
int index;
void OUT(bool b) {
static int index = 0;
printf("Collection #%d\n", ++index);
if (b) {
printf("Can be divided.\n\n");
}
else {
printf("Can't be divided.\n\n");
}
}
int INput(void) {
int total_ = 0;
for (int i = 0; i < 6; i++) {
scanf("%d", &n[i]);
total_ += (i + 1)*n[i];
for (int j = 1; j <= n[i]; j <<= 1) {
val[index++] = (i + 1)*j;
n[i] -= j;
}
if (n[i]) {
val[index++] = (i + 1)*n[i];
}
}
return total_;
}
int main(void) {
int total;
int index = 0;
while (1) {
index = 0;
total = INput();//录入下一次信息
if (!total)break;//全0
if (total & 1)OUT(false);//总价值为奇数不可分割
else {//尝试分割
total >>= 1;
int i, j;
memset(dp, 0, sizeof(dp));//初始化dp数组
for (i = 0; i < index; i++) {//物品从第一个一次排列
for (j = total; j >= val[i]; j--) {//01倒序
dp[j] = max(dp[j], dp[j - val[i]] + val[i]);
}
}
if (dp[total] == total)OUT(true);
else OUT(false);
}
}
system("pause");
return 0;
}
母函数:
# include<iostream>
# include<algorithm>
# define Inf 120000
using namespace std;
int n[6];
int a[Inf], b[Inf];
void OUT(bool b) {
static int index = 0;
if (index)cout << endl;
cout << "Collection #" << ++index << ":" << endl;
if (b) {
cout << "Can be divided." << endl;
}
else {
cout << "Can't be divided." << endl;
}
}
int INput(void) {
int total_ = 0;
for (int i = 0; i < 6; i++) {
cin >> n[i];//录入弹珠信息
total_ += (i + 1)*n[i];
}
return total_;
}
int main(void) {
int total = INput();//拿到第一个输入的价值
while (!((*max_element(n, n + 6)) == 0)) {//全0不做
if (total & 1)OUT(false);//总价值为奇数不可分割
else {//尝试分割
total /= 2;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
int i, j, k;
for (i = 0; i<=total&&i <= n[0]; i++) a[i] = 1;
for ( i = 1; i < 6; i++) {//共6个表达式,从第2个表达式到第6个表达式
if (!n[i])continue;//个数为0,第i个表达式不存在
for ( j = 0; j <= total; j++) {//计算出的表达式指数从0循环到total
for (k = 0; a[j] && k <= total&&k <= (n[i] * (i + 1)); k += i+1) {//for (k = 0;k <= coin[i] * i; k += i)
if (j + k > total)break;
b[j + k] += a[j];
}
}
for (k = 0; k <= total; k++) {
a[k] = b[k]; b[k] = 0;
}//刷新数组a的值,b数组清零
}
if (a[total])OUT(true);
else OUT(false);
}
total = INput();//录入下一次信息
}
system("pause");
return 0;
}
DFS暴搜:
# include<iostream>
# include<algorithm>
//# include<Windows.h>
using namespace std;
int n[6] = { 0 };
int ans, total, flag;
int Visit[6];
void OUT(bool b) {
static int index = 0;
if (index)cout << endl;
cout << "Collection #" << ++index << ":" << endl;
if (b) {
cout << "Can be divided." << endl;
}
else {
cout << "Can't be divided." << endl;
}
}
int INput(void) {
int total_ = 0;
for (int i = 0; i < 6; i++) {
cin >> n[i];//录入弹珠信息
Visit[i] = n[i];
total_ += (i+1)*n[i];
}
return total_;
}
void Fen(int index) {//index 层数一共6层,i第几个物品 n[i]为该层有的物品数
for (int i = index; i < 6 && !flag; i++) {
if (!index) {//0 层 ans =0;初始化访问表
ans = 0;
for (int j = 0; j < 6; j++) {
Visit[j] = n[j];
} //初始化访问表
}
if (!Visit[i])continue;
for (int k = 0; k <= n[i]; k++) {//首先不拿---直到拿n[i]个
Visit[i] -= k;//先拿K个
ans += (i + 1)*k; //得到K个总价值
if (ans < (total / 2)) {//价值小于目标数
Fen(i + 1);//递归到下一层
ans -= (i + 1)*k; //拿回的东西放回去
Visit[i] += k;
}
else if (ans == total / 2) {
flag = true; return;//找到并返回
}
else {//价格已经超出了 剪枝
ans -= (i + 1)*k; //东西放回去 结束
Visit[i] += k;
return;
}
}
}
}
int main()
{
total = INput();//拿到第一个输入的价值
while (!((*max_element(n, n + 6)) == 0)) {//全0不做
if (total & 1)OUT(false);//总价值为奇数不可分割
else {//尝试分割
flag = false;//未找到
Fen(0);//从0开始找
if (flag)OUT(true);
else OUT(false);
}
total = INput();//录入下一次信息
}
system("pause");
return 0;
}
因为超时所以不知道准确答案,因此我写了个检测......用的别人正确的AC码做参考:随机生成了10W个数据显示是对的
# include<iostream>
# include<algorithm>
#include <cstdio>
#include <cstring>
//# include<Windows.h>
using namespace std;
int n[6] = { 0 };
int a[6];
int ans, total, flag;
int Visit[6];
const int SIZE = 120000 + 16;
int dp[SIZE];
void Fen(int index) {//index 层数一共6层,i第几个物品
for (int i = index; i < 6 && !flag; i++) {
if (!index) {//0 层 ans =0;初始化访问表
ans = 0;
for (int j = 0; j < 6; j++) {
Visit[j] = n[j];
} //初始化访问表
}
if (!Visit[i])continue;
for (int k = 0; k <= n[i]; k++) {//首先不拿---直到拿n[i]个
Visit[i] -= k;//先拿K个
ans += (i + 1)*k; //得到K个总价值
if (ans < (total / 2)) {//价值小于目标数
Fen(i + 1);//递归到下一层
ans -= (i + 1)*k; //拿回的东西放回去
Visit[i] += k;
}
else if (ans == total / 2) {
flag = true; return;//找到并返回
}
else {//价格已经超出了 剪枝
ans -= (i + 1)*k; //东西放回去 结束
Visit[i] += k;
return;
}
}
}
}
void RAND(void) {
total = 0;
for (int i = 0; i < 6; i++) {
n[i] = rand() % 5 + 1;
a[i] = n[i];
Visit[i] = n[i];
total += (i + 1)*n[i];
}
}
bool My(void) {
if (total & 1)return false;//总价值为奇数不可分割
else {//尝试分割
flag = false;//未找到
Fen(0);//从0开始找
if (flag)return true;
else return false;
}
}
bool check()
{
for (int i = 0; i<6; i++)
if (a[i] != 0)
return true;
return false;
}
bool YO(void) {
int sum;
int t = 0;
while (true)
{
sum = 0;
for (int i = 0; i<6; i++)
{
sum += (i + 1)*a[i];
}
if (!check())
break;
if (sum % 2 == 1)
{
return false;
}
else
{
memset(dp, -1, sizeof(dp));
int k = sum / 2;
dp[0] = 0;
for (int i = 0; i<6; i++)
{
for (int j = 0; j <= k; j++)
{
if (dp[j] >= 0)
{
dp[j] = a[i];
}
else if (j<(i + 1) || dp[j - (i + 1)] <= 0)
{
dp[j] = -1;
}
else
{
dp[j] = dp[j - (i + 1)] - 1;
}
}
}
if (dp[k] >= 0)
{
return true;
}
else
{
return false;
}
}
}
}
int main()
{
bool re1, re2;
int index = 0;
while((index+1)<10000){
cout << ++index << endl;
RAND();
re1 = My();
re2 = YO();
if (re1 != re2) {
cout << "出现不同结果:" << endl;
cout << "--------------------" << endl;
cout << "MY:" << re1 << endl;
cout << "--------------------" << endl;
cout << "--------------------" << endl;
cout << "YO:" << re2 << endl;
cout << "--------------------" << endl;
cout << "--------------------" << endl;
cout << "n 的情况: " << endl;
for (int i = 0; i<6; i++)
{
cout <<i+1<<" : "<< a[i] << " "<<n[i]<<endl;
}
cout << "--------------------" << endl;
getchar();
}
}
system("pause");
return 0;
}