首先上面的兩道題都是同一道題,之所以同時拿出來是因為
hdu 的資料比 poj 的水,所以想區分一下。
hdu 的資料對時間要求不高
但是 poj 如果你想用簡單的 多重揹包解決的話,就會tle 別問我怎麼知道。
首先大家肯定會想到用多重揹包來做
畢竟題意可以巢狀模板如下
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 100010;
int dp[maxn];
int c[maxn],w[maxn];
int v;
void zeroonepack(int cost,int wei) // 01
}void completepack(int cost,int wei) // 完全
}void multiplepack(int cost,int wei,int cnt) //多重
else
zeroonepack(cnt*cost,cnt*wei);
}}int main()
return
0;}
額,**是對的,答案也是對的,但是你會發現他超時了,因為複雜度是o(v*σn[i]) ,所以太大,hdu 和 poj 都交不對。
所以我們就想優化一下,於是按照老思路,可不可以減少多重揹包對數量的迴圈次數呢?
我們把乙個物品根據數量把它變成多個物品,怎麼變會少一些時間呢?
答案是根據二進位制來變。
數量為num的物品,我們把它分成係數為1,2,4,8 ···· 2^n (2^n<= num)的話,選的時候花費和價值都乘以這個係數是不是就可以把它優化的分為幾個物品。
並且顯然滿足num = 1+2+4+8+2^n (2^n<= num)。
這樣的話時間就變成o(v*σlog n[i]) 的01揹包了。
**如下
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 100010;
int dp[maxn];
int c[maxn],w[maxn];
int v;
int main()
cnt -= k;
}if(cnt)
}int sum = 0;
for(int i=1;i<=v;i++) if(dp[i]) sum++;
printf("%d\n",sum);
}return
0;}
然而,這樣子的**只能過了hdu的資料,對於poj上的資料,還是超時。
現在怎麼辦,我根據網上其他人的**看出了怎麼優化。
第乙個優化就是,再開乙個陣列來記錄某個數用了多少次,dp陣列就直接用來標記這個數有沒有組成過,這個優化我覺得比較很重要
第二個優化就是計數答案就直接在迴圈裡面記錄
**如下
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 100010;
int dp[maxn];
int sum[maxn];
int c[maxn],w[maxn];
int v;
int main()}}
printf("%d\n",ans);
}return
0;}
hdu 2844 多重揹包)
思路 其實就是多重揹包的應用,只是這裡價值和重量是相等的,因此最後計數是要計價值和重量相等的個數 1 include2 include3 const int n 100010 4 using namespace std 5int n,m 67 struct nodenode n 100 11 int...
hdu2844 多重揹包
讀題能力還是不行,英文水平不夠,只能靠翻譯 華沙人用硬幣。他們有價值a1 a2 a3的硬幣 一枚銀幣。一天,希比克斯開啟錢包,發現裡面有一些硬幣。他決定在附近的一家商店買一塊非常好的手錶。他想支付確切的 不找零 他知道 不會超過m,但他不知道手錶的確切 你要寫乙個程式,它讀取n,m,a1,a2,a3...
hdu 2844 多重揹包
真爽啊 打完一把絕對carry的亞索 來做這題 一發ac touch me 這題 反正資料很大 不用二進位制拆分 肯定tle的 反正 二進位制拆分 很簡單的啊 不會的 現在看我 學下就好了。1 include 2 include 3 using namespace std 45 const int ...