P3423 [POI2005]BAN-Bank Notes
阿新 • • 發佈:2020-08-04
仍然是要優化的,但是輸出方案是非常噁心的
一維爆炸,以下為二進位制優化做法
關鍵是如果最後到著找方案的話,就比如說樣例
5的最少方法就是一個5,但是因為dp的順序是逆序。會把10指向5,然後5指向0
、??,但是隻有一個啊。所以不能倒序
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=200001; int cnt; int num[maxn],ca[maxn]; int num1[maxn],ca1[maxn]; int dp[maxn]; int k; int aimm,n; int ans[maxn]; int ord[maxn]; int used[maxn]; int sum; bool tu[3010][20010]; int main(){ memset(dp,0x7f,sizeof(dp)); dp[0]=0; scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&ca[i]); ord[ca[i]]=i; } for(int i=1;i<=n;++i){ scanf("%d",&num[i]); } scanf("%d",&aimm); for(int i=1;i<=n;++i){ for(int j=1;j<=num[i];j=j<<1){ cnt++; num1[cnt]=j; ca1[cnt]=j*ca[i]; num[i]-=j; ord[cnt]=i; } if(num[i]){ cnt++; num1[cnt]=num[i]; ca1[cnt]=num[i]*ca[i]; ord[cnt]=i; } } for(int i=1;i<=cnt;++i){ for(int j=aimm;j>=ca1[i];--j){ if(dp[j]>dp[j-ca1[i]]+num1[i]){ dp[j]=dp[j-ca1[i]]+num1[i]; tu[i][j]=1; } } } cout<<dp[aimm]<<endl; while(aimm){ while(!tu[cnt][aimm]&&cnt) --cnt;//是誰變成了aimm? //當然,肯定是後面的變前面的 aimm-=ca1[cnt];//去掉貢獻 ans[ord[cnt]]+=num1[cnt]; --cnt;//接著找 } for(int i=1;i<=n;++i){ cout<<ans[i]<<" "; } return 0; }