T1:
题目大意:给定n个物品,每个物品有两个属性A[i]和B[i]。选择一些物品使得C*D最大化,其中C为所选物品中A[i]的不同的数字个数,D为所选物品中B[i]的总和。
主要思路:由于A[i]比较小,所以可以对不同的A[i]进行一次dp,f[I]代表从所有A[i]==I的物品中选择一个子集使得权值和最大。g[I]代表选择了I个不同的A[i]所获得的最大权值。 g[I]=max(g[I],g[I-1]+f[J])。max(g[I]*I)就是答案。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int f[200];
class AlienAndHamburgers{
public:
int getNumber(vector <int> type, vector <int> taste){
int n=type.size();
for (int i=0; i<=100; ++i) f[i]=-200000;
for (int i=0; i<n; ++i)
f[type[i]]=max(f[type[i]],max(f[type[i]]+taste[i],taste[i]));
sort(f,f+101);
int ans=0,ans1=0;
for (int i=100; i>=1; --i){
ans1+=f[i];
if (f[i]<-150000) break;
ans=max(ans1*(101-i),ans);
}
return ans;
}
};
T2:
题目大意:给你{1,2....,2n}2n个数字,将它们分成两个有n个元素的几何。对于所有1<=i<=n,|A[i]-B[i]|>=K,A[i]为第一个组的第i小的元素,B[i]为第二组的第i小的元素。求有多少不同的方案。
主要思路:由于K<=10,所以可以考虑状压dp,f[i][j][opt]代表处理到第i个数字,小于i-K的数字有j个还没有分组,大于等于i-K且小于i的数字有opt状态还没分组的方案数。每次我们可以选择将第i个数进行分组或者忽略i。这样f求出来的方案必定是默认A[i]>=B[i],所以我们再定义g[i]:两个集合的前i个元素已经分好的方案数。g[i]=sigma(g[j]*f[(i-j)*2][0][0]),代表两个集合第j个元素的大小顺序和第j+1...i个元素的大小顺序不同,即 A[j]>B[j] -> A[k]<B[k],k=j+1...i。这样算出来的两个集合是不分顺序的,所以最终答案为g[n]*2。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int f[101][101][1000];
int g[51];
const int P=1000000007;
int c[101][101];
int find(int x,int y){
c[0][0]=1;
for (int i=1; i<=x; ++i)
for (int j=0; j<=min(i,y); ++j)
c[i][j]=(j==0)?1:(c[i-1][j]+c[i-1][j-1])%P;
return c[x][y];
}
class AlienAndSetDiv1{
public:
int getNumber(int N, int K){
if (K==1) return find(2*N,N);
N*=2;
memset(f,0,sizeof(f));
f[0][0][0]=1;
--K;
int m=(1<<K)-1;
for (int i=0; i<N; ++i)
for (int j=0; j<=i; ++j)
for (int k=0; k<=m; ++k)
if (f[i][j][k]){
int z=0,opt=((k<<1)+1) & m;
if ((k & (1<<(K-1)))>0) ++z;
f[i+1][j+z][opt]=(f[i+1][j+z][opt]+f[i][j][k])%P;
opt=(k<<1) & m;
if (j>0)
f[i+1][j+z-1][opt]=(f[i+1][j+z-1][opt]+f[i][j][k])%P;
}
memset(g,0,sizeof(g));
g[0]=1;
N/=2;
for (int i=1; i<=N; ++i)
for (int j=0; j<i; ++j)
g[i]=(g[i]+(long long)g[j]*f[(i-j)*2][0][0] %P)%P;
return g[N]*2%P;
}
};