vijos 1037 背包+标记

描述

2001年9月11日,一场突发的灾难将纽约世界贸易中心大厦夷为平地,Mr. F曾亲眼目睹了这次灾难。为了纪念“9?11”事件,Mr. F决定自己用水晶来搭建一座双塔。

Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建。但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少。所以他来请你帮忙。

给定水晶的数量N(1≤N≤100)和每块水晶的高度Hi(N块水晶高度的总和不超过2000),你的任务是判断Mr. F能否用这些水晶搭建成一座双塔(两座塔有同样的高度),如果能,则输出所能搭建的双塔的最大高度,否则输出“Impossible”。

格式

输入格式

输入的第一行为一个数N,表示水晶的数量。第二行为N个数,第i个数表示第i个水晶的高度。

输出格式

输出仅包含一行,如果能搭成一座双塔,则输出双塔的最大高度,否则输出一个字符串“Impossible”。

样例1

样例输入1[复制]

5
1 3 4 5 2

样例输出1

7

题意:给出一堆数,将其分为两堆(可以不取数),问能否使两堆大小相同,能则输出最大。

思路:之前写的分两堆找差值最小的变化版,同样使用标记进行转移即可。dp[i][j]代表的是一堆值为i另一堆值为j是否有符合条件的方案。

/** @Date    : 2016-11-28-21.10
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version :
  */
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
//#include<bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+2000;

int a[200];
bool dp[2100][2100];
int main()
{
    int n;
    while(cin >> n)
    {
        int sum = 0;
        for(int i = 1; i <= n; i++)
            scanf("%d", a + i), sum += a[i];

        MMF(dp);

        dp[0][0] = 1;
        for(int k = 1; k <= n; k++)
            for(int i = sum; i >= 0; i--)
            {
                for(int j = sum; j >= 0; j--)
                {
                    if(dp[i][j])
                    {
                        dp[i+a[k]][j] = dp[i][j+a[k]] = 1;
                    }
                }
            }
        int flag = 1;
        for(int i = sum; i > 0; i--)//这里0不可以有阿!
            if(dp[i][i] == 1)
            {
                flag = 0;
                printf("%d\n", i);
                break;
            }
        if(flag)
            printf("Impossible\n");
    }
    return 0;
}
时间: 2024-10-04 07:20:26

vijos 1037 背包+标记的相关文章

shu_1299 vijos 1037(搭建双塔)

http://202.121.199.212/JudgeOnline/problem.php?cid=1078&pid=7 分析: 经典DP题 dp[ i ][ j ]:前i个水晶搭建的高度差为 j 的双塔中较高塔的高度: dp[ i ][ j ] = d[ i-1 ][ j ]  ,                       不放第i个水晶: dp[ i ][ j ] = f[ i-1 ][ h[i]-j ] + j,               第i个水晶放在较矮的塔上,原来较矮的塔变成较

vijos 1426 背包+hash

背景 北京奥运会开幕了,这是中国人的骄傲和自豪,中国健儿在运动场上已经创造了一个又一个辉煌,super pig也不例外……………… 描述 虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的.但是运动员为了提高成绩难免要服用一些,super pig也不例外.为了不被尿检检查出来,这些药品就只能选一些不容易被发现的来服用.但是奥委会关于兴奋剂检查有很多个指标,只有尿检中各项数值均不高于规定指标才算成阴性(“你没服兴奋剂”),所以如何服用适量的药品使自己的水平达到最高是每个运动员困扰的问题. 现在有

vijos 1025 背包 *

链接:点我 输入顺序又反了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=

vijos 1037 ***

链接:点我 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 const int v = 2000 + 5; 7 const int MaxN = 100 + 5; 8 int N, sum, num[MaxN], dp[2][v]; 9 int main() { 10 int i, j,

vijos 1037 搭建双塔 【DP】

% 这题是小猫给我讲的 % 题目: Mr. F有N块水晶,每块水晶有一个高度,他想用这N块水晶搭建两座有同样高度的塔,使他们成为一座双塔,Mr. F可以从这N块水晶中任取M(1≤M≤N)块来搭建.但是他不知道能否使两座塔有同样的高度,也不知道如果能搭建成一座双塔,这座双塔的最大高度是多少.所以他来请你帮忙. 给定水晶的数量N(1≤N≤100)和每块水晶的高度Hi(N块水晶高度的总和不超过2000),你的任务是判断Mr. F能否用这些水晶搭建成一座双塔(两座塔有同样的高度),如果能,则输出所能搭建

vijos P1836HYS与七夕节大作战 (01背包之2--转换dp对象)

题目:vijos P1836HYS与七夕节大作战 题意: n个对象,每价值为vi,比重pi,总容量100 分析: 类似背包重量的比重pi为实数,不能作为下标,所以改变dp对象 将求容量100内的最大价值 → 求相应价值的最小容量, 则容量第一个≤100的价值,为符合条件的价值最大的值 状态:dp[v]:价值为v的最小容积 转移方程:         dp[V] = min(dp[V], dp[V-v[i]] + p[i]); 核心: for(i = 1; i<=n; i++) {     for

UVA - 10032 Tug of War (二进制标记+01背包)

Description Problem F: Tug of War A tug of war is to be arranged at the local office picnic. For the tug of war, the picnickers must be divided into two teams. Each person must be on one team or the other; the number of people on the two teams must n

Vijos 1180 (树形DP+背包)

题目链接: https://vijos.org/p/1180 题目大意:选课.只有根课选了才能选子课,给定选课数m, 问最大学分多少. 解题思路: 树形背包.cost=1. 且有个虚根0,取这个虚根也要cost,所以最后的结果是dp[0][m+1]. 本题是cost=1的特殊背包问题,在两个for循环上有一个优化. for(f+1...j....cost) for(1....k...j-cost) 其中f为当前已经dfs子结点个数.之所以+1,是因为根要预留一个空间. f+=dfs(t),dfs

【动态规划】【归并】Vijos P1412 多人背包

题目链接: https://vijos.org/p/1412 题目大意: 求01背包的前K优解,要求必须装满(1<=K<=50 0<=V<=5000 1<=N<=200) 题目思路: [动态规划] f[j][k]表示花费为j的第k优解. 合并的过程用归并. 1 // 2 //by coolxxx 3 ////<bits/stdc++.h> 4 #include<iostream> 5 #include<algorithm> 6 #in