一道我觉得挺难的DP
这道题做到我好崩溃~~原来我想的思路是递归,但这肯定会越栈,后来看到了别人的思路,挺巧妙的,
为了实现自底向上的表记录,他设计了 ff[i][j]是拼到了i长,j还剩下的个数。 还有一个
bool flag[ ],最后的最大值就是从这bool表中找出来的。 值得回味~~
#include<stdio.h>
#include<string>
#include<string.h>
using namespace std;
bool flag[100001];//cash最多就100000;
int ff[100001][11],cash,N;
typedef struct money
{
int m,l;
};
money mm[11];
int main()
{
freopen("acm.txt","r",stdin);
int i,j,k;
while(scanf("%d",&cash)!=EOF)
{
memset(flag,0,sizeof(flag));
flag[0]=true;
memset(ff,0,sizeof(ff));
scanf("%d",&N);
for(i=0;i<N;i++)
{
scanf("%d%d",&mm[i].l,&mm[i].m);
ff[0][i]=mm[i].l;
}
for(i=0;i<=cash;i++)
{
for(j=0;j<N;j++)
{
if(ff[i][j]&&i+mm[j].m<=cash&&!flag[i+mm[j].m]) //ff[i][j] 是拼到了i长,j还剩下的个数。
{
for(k=0;k<N;k++)
ff[i+mm[j].m][k]=ff[i][k];
flag[i+mm[j].m]=true;
ff[i+mm[j].m][j]--;//仅j的个数减少了。
}
}
}
for(i=cash;i>=0;i--)//小于cash的最大的一个即为答案。
if(flag[i])
break;
printf("%d\n",i);
}
return 0;
}
我说崩溃是因为我按照他的思路自己写了一遍,其实基本上是一样的,但就是AC不了,晕~~~
#include<iostream.h>
#include<stdio.h>
class node{
public:
node(int a,int n):amount(a),note(n){}
int amount;
int note;
};
int ff[100001][11] ; //ff[i][j]记录的是当累积的money为i是,j剩下的个数
bool flag[100001]; //若flag[i]为true,则i是能被累加而得到的
void main(){
int request,N,i,j,k,a,n;
node* money[11];
freopen("acm.txt","r",stdin);
while(scanf("%d",&request)!=EOF){
for(i=0;i<100001;i++)
flag[i]=false;
for(i=0;i<100001;i++)
for(j=0;j<11;j++)
ff[i][j]=0;
scanf("%d",&N);
for(i=0;i<N;i++){
scanf("%d%d",&a,&n);
money[i]=new node(a,n);
}
flag[0]=true;
for(i=0;i<N;i++) ff[0][i]=money[i]->amount;
for(i=0;i<=request;i++){
for(j=0;j<N;j++){
if(ff[i][j] && (i+money[j]->note)<=request && !flag[i+money[j]->note]){
//ff[i+(money[j]->note)][j]=ff[i][j]-1, flag[i+(money[j]->note)]=true;
for(k=0;k<N;k++)
ff[i+money[j]->note][k]=ff[i][k];
flag[i+money[j]->note]=true;
ff[i+money[j]->note][j]--;
}
}
}
i=request;
while(!flag[i]&&i>=0) i--;
printf("%d\n",i);
}
}