注意记录路径时path要五维,不能滚动数组,因为没有第几个物品来标明顺序的话,就可能在某个物品的dp中导致path 的两个状态对应同一个物品,导致wa或者超时!
还有dp数组可以用short int存储
ac代码:
#include<bits/stdc++.h> using namespace std; #define per(i,a,b) for(int i=a;i <= b;i++) #define Max(a,b) a=max(a,b) #define Min(a,b) a=min(a,b) #define Sz(x) (int)x.size() typedef long long ll; ll gcd(ll a,ll b){while(b){ll t=b;b=a%b;a=t;} return a;} const int inf=0x3f3f3f3f; #define siz 37 int n,dp[siz][siz][siz][siz],p[siz],a[siz],c[siz],m[siz],g[siz],P,A,C,M; bool path[siz][siz][siz][siz][siz]; set<int>st; void init() { st.clear(); memset(dp,0,sizeof(dp)); memset(path,false,sizeof(path)); } int main() { std::ios::sync_with_stdio(false); while(scanf("%d",&n)!=EOF){ init(); int px,ax,cx,mx; for(int i=0;i<n;i++){ scanf("%d %d %d %d %d",&p[i],&a[i],&c[i],&m[i],&g[i]); } scanf("%d %d %d %d",&P,&A,&C,&M); per(pxx,p[0],P)per(axx,a[0],A)per(cxx,c[0],C)per(mxx,m[0],M){dp[pxx][axx][cxx][mxx]=g[0];path[0][pxx][axx][cxx][mxx]=true;} for(int i=1;i<n;i++){ for(px=P;px>=p[i];px--){ for(ax=A;ax>=a[i];ax--){ for(cx=C;cx>=c[i];cx--){ for(mx=M;mx>=m[i];mx--){ if(dp[px][ax][cx][mx]<(dp[px-p[i]][ax-a[i]][cx-c[i]][mx-m[i]]+g[i])){ dp[px][ax][cx][mx]=(dp[px-p[i]][ax-a[i]][cx-c[i]][mx-m[i]]+g[i]); path[i][px][ax][cx][mx]=true; } } } } } } px=P;ax=A;cx=C;mx=M; int tmp=n-1; /*while(path[tmp][px][ax][cx][mx]){ px-=p[tmp];ax-=a[tmp];cx-=c[tmp];mx-=m[tmp]; tmp=path[px][ax][cx][mx]; if(tmp==-1)break; st.insert(tmp); }*/ while(tmp>=0&&px>=0&&ax>=0&&cx>=0&&mx>=0){ if(path[tmp][px][ax][cx][mx]){ st.insert(tmp); px-=p[tmp]; ax-=a[tmp]; cx-=c[tmp]; mx-=m[tmp]; } tmp--; } printf("%d ",st.size()); if(st.empty()==true)continue; set<int>::iterator it=st.begin(); printf("%d",*it); it++; for(;it!=st.end();it++){ printf(" %d",*it); } printf(" "); } return 0; }