【发布时间】:2016-01-24 20:40:27
【问题描述】:
以下问题是在比赛中(现在已经结束) 比赛link.
它似乎是经典硬币面额问题的变体 -
给定一个包含硬币值和数字 n 的数组(k 个元素)。我们需要回答可以计算 n 面额的方法的数量。我们可以通过DP 解决它,这将花费O(n*k) 时间。现在在比赛问题中,不是给出硬币值数组,而是有一个值 m,并且硬币值都是 m ex 的所有可能幂。 n= 200, m=3. 所以我们有[3^0, 3^1, 3^2, 3^3, 3^4] 的硬币值,更高的幂对于这个例子没有用]。
我在这里使用了DP 方法,但它提供了TLE。通过查看时间限制testcases<=10000、n<=10000、m<=10000,我假设我们必须在O(n) 时间内解决给定n,m 的问题[可能还需要优化这个。请帮我解决这个问题。
我使用DP的解决方案。
#include <bits/stdc++.h>
#include <stdio.h>
using namespace std;
int solve(vector<int>&vec, int n){
cout<<"n= "<<n<<": m= "<<vec.size()<<endl;
int r=n+1, c=vec.size()+1;
vector<int>row(c,0);
vector<vector<int> >dp(r, row);
for(int i=0;i<c;i++)
dp[0][i]=1;
for(int i=1;i<r;i++){
for(int j=1;j<c;j++){
int a=0;
if(i-vec[j-1]>=0)
a=dp[i-vec[j-1]][j];
dp[i][j]=a+dp[i][j-1];
}
}
return dp[n][c-1];
}
int main()
{
ios::sync_with_stdio(false);
int tc,n,m;
cin>>tc;
while(tc--){
cin>>n>>m;
vector<int>temp;
int index=0;
temp.push_back(1);
while(temp[index]*m<=n){
temp.push_back(temp[index]*m);
index++;
}
int result=solve(temp,n);
cout<<result<<endl;
}
return 0;
}
【问题讨论】:
-
与问题无关,但如果您包含来自
bits的任何内容,则说明您做错了 -bits包含 libstdc++ 的实现细节内容,不应该直接包含在内。跨度> -
您可能应该使用这样一个事实,即用硬币 m^0,m^1,m^2... 给出 n 总和的方法数与给 m*n 硬币 m^1,m^2,...
标签: c++ dynamic-programming partitioning combinatorics coin-change