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.网络流(稍后填坑)