bzoj3824[Usaco2014 Dec]Guard Mark 奶牛叠罗汉(II)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3824
题目大意:
题解:
状压dp
f[i]表示已经选了i的奶牛来叠的最大安全因子为多少。
因为已经知道选了什么,所以高度是一定的(用了sm[i]来存)
对于每个sm[i]≥L,ans=max(ans,f[i])。选个最大值~
小吐槽:神tm一开始以为要用long long,然后I64d交bzoj交了好几次!显示WA!让我还以为USACO的数据水到了这种地步..改成int之后快了两秒!两秒啊!还能说什么!
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; // typedef long long LL; #define maxn 1100000 #define N 30 const int inf = 1e9; int f[maxn],sm[maxn]; int h[N],w[N],s[N]; int mymax(int x,int y){return (x>y)?x:y;} int mymin(int x,int y){return (x<y)?x:y;} int main() { //freopen("guard.in","r",stdin); //freopen("guard.out","w",stdout); int n,L,i,k,mx,sum=0,ans; scanf("%d%d",&n,&L); for (i=1;i<=n;i++) { scanf("%d%d%d",&h[i],&w[i],&s[i]); sum+=h[i]; }mx=(1<<n)-1;sm[0]=0;f[0]=inf; for (i=1;i<=mx;i++) f[i]=-1; ans=-1;sm[mx]=sum; for (i=0;i<=mx;i++) { for (k=1;k<=n;k++) if (!(i&(1<<k-1))) { int xx=i|(1<<k-1); if (w[k]>f[i]) continue; f[xx]=mymax(f[xx],mymin(s[k],f[i]-w[k])); sm[xx]=sm[i]+h[k]; } if (sm[i]>=L && f[i]!=inf) ans=mymax(ans,f[i]); } if (ans==-1) printf("Mark is too tall\n"); else printf("%d\n",ans); return 0; }