EOJ 2112 WYI & EOJ 2113 WYII

3 篇文章 0 订阅
http://acm.cs.ecnu.edu.cn/problem.php?problemid=2112

http://acm.cs.ecnu.edu.cn/problem.php?problemid=2113


题意:

背包问题,只不过数据范围变了。假定V为容量,ti为每个物品的重量,ki为价值,求能获得的最大价值。

(一)

2112 V特别大,n大,sum(k)比较小。改为要获得价值i,需要花费的最少时间 ,然后判断下,从时间<=L的结果中取。(也就是把sum(k)看成容量,t[i]看成价值,只不过求最小)

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
 
#define inf 0x3f3f3f3f
int a[20005];//价值为i是的最小时间
int main()
{
	int cas;
	scanf("%d", &cas);
	while(cas --){
		int n,l;
		scanf("%d%d", &n, &l);
		int m = n * 200;
		memset(a, 0x3f, sizeof(a));
		a[0] = 0;
		while(n --){
			int t, k;
			scanf("%d%d", &t, &k);
			for(int i = m; i>= k; i--){
				a[i] = min(a[i-k]+t, a[i]);
 
			}
		}
		int ans = 0;
		for(int i=m; i>=0;i --){
			if(a[i] <= l)
			{
				ans = i;
				break;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

(二)
2113

K, V 都特别大,n比较小。

1.DFS +  剪枝

#include <stdio.h>
typedef long long LL;
const LL maxn = 100;
bool visited[maxn];
LL t[maxn];
LL k[maxn];
LL sum[maxn];
LL n,l,ans;
template<class T> inline void checkMin(T &a,const T b){if (b<a) a=b;}
template<class T> inline void checkMax(T &a,const T b){if (a<b) a=b;}
void dfs(LL depth, LL limit, LL value)
{
	if( limit>l )return;
	if( value+sum[depth]<=ans )return;
	if( depth==n ){
		checkMax(ans, value);
		return ;
	}
	dfs(depth+1, limit+t[depth], value+k[depth]);
	dfs(depth+1, limit, value);
}
int main()
{
	LL cas;
	scanf("%lld",&cas);
	while(cas --){
		scanf("%lld%lld",&n,&l);
		for( LL i=0;i<n;i++ ){
			scanf("%lld%lld",&t[i],&k[i]);
		}
		sum[n] = 0;
		for( LL i=n-1;i>=0;i-- ){
			sum[i] = sum[i+1] + k[i];
		}
		ans = 0;
		dfs(0, 0, 0);
		printf("%lld\n", ans);		
	}
	return 0;
}
2.枚举前n/2个,后n-n/2个,然后把他们变成随时间价值增加的不减序列,二分查找(两个指针,一个从前往后,一个从后往前,复杂度也是nlogn)

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
 
using namespace std;
 
#define DO(n) for ( int ____n ## __line__ = n; ____n ## __line__ -- ; )
 
#define ALL(A) A.begin(), A.end()
#define BSC(A, x) (lower_bound(ALL(A), x) - A.begin())
#define CTN(T, x) (T.find(x) != T.end())
#define SZ(A) int(A.size())
#define PB push_back
#define MP(A, B) make_pair(A, B)
#define fi first
#define se second
 
typedef long long LL;
 
 
typedef vector<int> VI;
typedef map<int, int> MII;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
 
 
template<class T> inline void RST(T &A){memset(A, 0, sizeof(A));}
template<class T> inline void FLC(T &A, int x){memset(A, x, sizeof(A));}
template<class T> inline void CLR(T &A){A.clear();}
 
//}
 
/** Constant List .. **/ //{
 
const int dx4[] = {-1, 0, 1, 0};
const int dy4[] = {0, 1, 0, -1};
 
const int dx8[] = {-1, 0, 1, 0 , -1 , -1 , 1 , 1};
const int dy8[] = {0, 1, 0, -1 , -1 , 1 , -1 , 1};
 
const int dxhorse[] = {-2 , -2 , -1 , -1 , 1 , 1 , 2 , 2};
const int dyhorse[] = {1 ,  -1 , 2  , -2 , 2 ,-2 , 1 ,-1};
 
const int MOD = 1000000007;
//int MOD = 99990001;
const int INF = 0x3f3f3f3f;
const LL INFF = 1LL << 60;
const double EPS = 1e-9;
const double OO = 1e15;
const double PI = acos(-1.0); //M_PI;
 
//}
 
template<class T> inline void checkMin(T &a,const T b){if (b<a) a=b;}
template<class T> inline void checkMax(T &a,const T b){if (a<b) a=b;}
//}
template<class T> inline T low_bit(T x) {return x & -x;}
/*****************************************************************/
PLL a[40];
int n;
LL k;
const int N = (1 << 15) + 9;
PLL ap[N] , an[N];
void solve(){
    scanf("%d%lld" , &n , &k);
    for (int i = 0 ; i < n ; ++i) scanf("%lld%lld" , &a[i].fi , &a[i].se);
    LL ans = 0;
    int pre = n >> 1;
    int nex = n - pre;
    int TOT = 1 << pre;
    int TAT = 1 << nex;
    for(int i = 0 ; i < TOT ; ++i){
        int ii = i;
        ap[i].fi = ap[i].se = 0;
        for (int j = 0 ; j < pre && ii; ++j){
            if (ii & 1){
                ap[i].fi += a[j].fi;
                ap[i].se += a[j].se;
            }
            ii >>= 1;
        }
    }
    for(int i = 0 ; i < TAT ; ++i){
        int ii = i;
        an[i].fi = an[i].se = 0;
        for (int j = 0 ; j < nex && ii; ++j){
            if (ii & 1){
                an[i].fi += a[j + pre].fi;
                an[i].se += a[j + pre].se;
            }
            ii >>= 1;
        }
    }
    sort(ap , ap + TOT);sort(an , an + TAT);
    for (int i = 1 ; i < TOT ; ++i) checkMax(ap[i].se , ap[i - 1].se);
    for (int i = 1 ; i < TAT ; ++i) checkMax(an[i].se , an[i - 1].se);
    int tail = TAT - 1;
    for (int i = 0 ; i < TOT && ap[i].fi <= k ; ++i){
        while(an[tail].fi + ap[i].fi > k) --tail;
        checkMax(ans , ap[i].se + an[tail].se);
    }
    printf("%lld\n" , ans);
}
int main(){
    int _;
    cin >> _;
    while(_--) solve();
}

3.网络流(稍后填坑)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值