最近在做DP的题目,然后各种智商捉急。感觉生科院有什么开发智力的实验我一定会去的。
Description
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.
Input
Output
Sample Input
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
Sample Output
8 4
咳咳~ 蒟蒻没什么本事来是非楼教主的题。无限OIZ中
题意大致为给出n种价值不同的硬币,分别是A1,A2,A3....An;和它们的数量C1,C2,C3....Cn;问Tony可以支付多少种总价值<=m,的钱。
很明显的多重背包,加二进制优化。然后 dp[ j ] = max ( dp[ j ] , dp[ j - A[ i ] ] + A[ i ] ) 交。TLE。。。。上网一查,一片抱怨TLE的,据说单调队列优化的也TLE了。
果然楼教主,果然男人八题。
然后膜拜了一些大牛。dp[ j ] 只需要用来表示是否组成了价值为 j 的钱就行了。dp[ j ] = (dp[ j - A[ i ] ] == 1 ) 然后还要用一个use数组计入A[ j ]的使用次数。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,m,ans;
int a[110],c[110],v[110];
int f[100100],s[100100];
while (scanf ("%d%d",&n,&m)!=EOF&&n&&m){
memset(f,0,sizeof(f));
ans=0;
for (int i=0;i<n;i++){
scanf ("%d",&a[i]);
}
for (int i=0;i<n;i++){
scanf("%d",&c[i]);
}
f[0]=1;
for (int i=0;i<n;i++){
memset(s,0,sizeof(s));
for (int j=a[i];j<=m;j++){
if (!f[j]&&f[j-a[i]]&&s[j-a[i]]<c[i]){
f[j]=1; // 标记价格为 j 的钱出现过
s[j]=s[j-a[i]]+1; // A[j] 使用 +1
ans++; // 统计方案数。
}
}
}
printf("%d\n",ans);
}
return 0;
}
Description
Help the cows build the tallest space elevator possible by stacking blocks on top of each other according to the rules.
Input
* Lines 2..K+1: Each line contains three space-separated integers: h_i, a_i, and c_i. Line i+1 describes block type i.
Output
Sample Input
3 7 40 3 5 23 8 2 52 6
Sample Output
48
Hint
From the bottom: 3 blocks of type 2, below 3 of type 1, below 6 of type 3. Stacking 4 blocks of type 2 and 3 of type 1 is not legal, since the top of the last type 1 block would exceed height 40.
和前面一题非常相似,奶牛们想去太空,所以打算用建造一个电梯。他们有 k 种不同的材料,每种材料的高度是 h_i ,数量是 c_i ,因为存在宇宙射线,每种材料的放置高度不可以超过 a_i 。
问能够达到的最大高度是多少。
和楼教主那题非常类似,用 dp[ i ] 数组记录 高度为 i 的情况是否出现过。当然,这里要先对材料按最大放置高度进行排序。dp时先考虑防止高度较小的。
处理方法和前面一题一样:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct Node{
int a,h,c;
};
bool cmp (Node a,Node b){
return a.h<b.h;
}
int main(){
int k,ans=0;
int use[40040];
int dp[40040];
Node s[404];
cin>>k;
for (int i=1;i<=k;i++){
scanf ("%d%d%d",&s[i].a,&s[i].h,&s[i].c);
}
sort(s+1,s+k+1,cmp);
memset(dp,0,sizeof(dp));
dp[0]=1;
for (int i=1;i<=k;i++){
memset(use,0,sizeof(use));
for (int j=s[i].a;j<=s[i].h;j++){ //<=s[i].h 不可以超过最大放置高度。
if(!dp[j]&&dp[j-s[i].a]&&use[j-s[i].a]<s[i].c){
dp[j]=1; //记录是否出现过。
use[j]=use[j-s[i].a]+1; //使用次数 + 1 。
if (j>ans) ans=j; //记录出现过得最大值 。
}
}
}
cout<<ans<<endl;
return 0;
}
dpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdpdp