【枚举+贪心】【TOJ3981】【ICPC Balloons】
给你N种不同颜色气球,每种气球有个数目 count[i],给的同种颜色气球可能是L尺寸,或M尺寸。
M个问题,每个问题有个解决人数ac[i]。
每个问题 要分配一种颜色的气球,尺寸要一样
现在 这些气球可能不符合条件 但是可以将一种气球颜色 刷成另一种(不管之前有没有),但是改变不了尺寸,问最少改变多少个气球颜色。
N《50 M《15;
枚举 2^M 次 考虑 某个问题是用L尺寸的还是M尺寸的
接下来就跟L,M无关了
然后贪心
大的一定先分配,分配完后 利用sum结算要凃的气球颜色数目,显然数量大的具有明显的优势。
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 10000000 using namespace std; struct ball { int size; int num; }A[100]; int maxac[100]; int n,m; int tot=0; int a[100]; int ans=10000000; bool cmp(ball a,ball b) { if(a.size==b.size) { return a.num<b.num; } else return a.size<b.size; } bool cmp2(int a,int b) { return a>b; } void input() { memset(a,0,sizeof(a)); ans=10000000; memset(maxac,0,sizeof(maxac)); memset(A,0,sizeof(A)); tot=0; char c; cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&A[i].num); getchar(); for(int i=1;i<=n;i++) { scanf("%c",&c); if(c=='L') A[i].size=1; else A[i].size=0,tot++; } for(int i=1;i<=m;i++) scanf("%d",&maxac[i]); sort(A+1,A+n+1,cmp); // sort(maxac+1,maxac+m+1,cmp2); } int getans(int t) { int K[100],T[100]; int R=0; int TOT=0,TTOT=0,sum1=0,sum2=0; for(int i=1;i<=n;i++) { if(A[i].size==t) { K[++TOT]=A[i].num; sum1+=A[i].num; } } sort(K+1,K+TOT+1,cmp2); for(int i=1;i<=m;i++) { if(a[i]==t) { T[++TTOT]=maxac[i]; sum2+=maxac[i]; } } sort(T+1,T+TTOT+1,cmp2); if(sum1<sum2) return oo; int pp1=0,pp2=0; for(int i=1;i<=TOT&&i<=TTOT;i++) { if(K[i]<=T[i]) { pp1+=K[i]; } else pp1+=T[i]; } return sum2-pp1; } void dfs(int p) { if(p==m+1) { int p[4]; for(int i=0;i<=1;i++) p[i]=getans(i); if(p[1]+p[0]<ans) ans=p[1]+p[0]; return ; } else { a[p]=1; dfs(p+1); a[p]=0; dfs(p+1); } } void solve() { ans=oo; dfs(1); if(ans==10000000) printf("-1\n"); else printf("%d\n",ans); } int main() { // freopen("a.in","r",stdin); // printf("%I64d",a==1>>3*234%333^2*234<<2); int T;cin>>T; while(T--) { input(); solve(); } }