您的位置:首页 > 其它

110.科技庄园(多重背包)(未结题)

2016-04-01 22:19 344 查看


3556 科技庄园[/b]

时间限制: 1
s

空间限制:
128000 KB

题目等级 :
黄金 Gold

题解

题目描述 Description

Life是codevs的用户,他是一个道德极高的用户,他积极贯彻党的十八大精神,积极走可持续发展道路,在他的不屑努力下STN终于决定让他在一片闲杂地里种桃,以亲身实践种田的乐趣,厉行节约,告诉人们节约的重要性!

春华秋实,在这个金秋的季节,Life带者他的宠物——PFT到了他的试验田,当他看见自己的辛勤成果时,心里是那个高兴啊!

这时Life对他的宠物PFT说:“你想不想吃桃啊?”

PFT兴奋的说:“好啊!”

Life说:“好吧,但是我只给你一定的时间,你必须在规定的时间之内回到我面前,否则你摘的桃都要归我吃!”

PFT思考了一会,最终答应了!

由于PFT的数学不好!它并不知道怎样才能在规定的时间获得最大的价值,但你是一个好心人,如果你帮助它,你的RP一定会暴涨的!

对于这个可以RP暴涨机会,你一定不会错过的是不是?

由于PFT不是机器人,所以他的体力并不是无限的,他不想摘很多的桃以至体力为0,而白白把桃给Life。同时PFT每次只能摘一棵桃树,每棵桃树都可以摘K次(对于同一棵桃每次摘的桃数相同)。每次摘完后都要返回出发点(PFT一次拿不了很多)即Life的所在地(0,0){试验田左上角的桃坐标是(1,1)}。

PFT每秒只能移动一个单位,每移动一个单位耗费体力1(摘取不花费时间和体力,但只限上下左右移动)。

输入描述 Input
Description

第一行:四个数为N,M,TI,A 分别表示试验田的长和宽,Life给PFT的时间,和PFT的体力。

下面一个N行M列的矩阵桃田。表示每次每棵桃树上能摘的桃数。

接下来N行M列的矩阵,表示每棵桃最多可以采摘的次数K。

输出描述 Output
Description

一个数:PFT可以获得的最大的桃个数。

样例输入 Sample
Input

4 4 13
20

10 0 0
0

0 0 10
0

0 0 10
0

0 0 0 0

1 0 0 0

0 0 2 0

0 0 4 0

0 0 0 0

样例输出 Sample
Output

10

数据范围及提示 Data Size &
Hint

【样例解释】

可以摘到1次(1,1)或1次(2,3)或1次(3,3),体力和时间不满足再摘桃了。

【数据范围】

对于M N TI A

10<=30%<=50

10<=100%<=100

对于K

10<=100%<=100

保证结果在longint范围内


分类标签 Tags 点此展开

背包型DP

代码:3个点没过

方法一:多重背包,

#include<
iostream >

#include< cstdio >

using namespace std;

int taosum=0,n,m,tim,tili;

long long int f[1001];

struct Tao{

long long int x,y;

long long int sum,cs;

};

Tao tao[2500001];

int t=0;

void input()

{

int k;

scanf("%d%d%d%d",&n,&m,&tim,&tili);

for(int i=1;i<=n;++i)//x

for(int
j=1;j<=m;++j)//y

{

scanf("%d",&k);

if(k!=0)

{

++t;

tao[t].x=i;

tao[t].y=j;

tao[t].sum=k;

}

}

t=0;

for(int i=1;i<=n;++i)

for(int j=1;j<=m;++j)

{

scanf("%d",&k);

if(k!=0)

{

t++;

tao[t].cs=k;

}

}

int p=t;

for(int i=1;i<=p;++i)

{

while(tao[i].cs!=1)

{

tao[i].cs--;

t++;

tao[t].x=tao[i].x;

tao[t].y=tao[i].y;

tao[t].sum=tao[i].sum;

}

}

}

int main()

{

input();

for(int i=1;i<=t;++i)

for(int
j=min(tim,tili);j>(tao[i].x+tao[i].y)*2;--j)

f[j]=max(f[j],f[j-2*tao[i].x-2*tao[i].y]+tao[i].sum);

printf("%d\n",f[min(tili,tim)]);

return 0;

}
方法二:二进制分法:
#include<
iostream >

#include< cstdio >

using namespace std;

int taosum=0,n,m,tim,tili;

long long int f[200001];

struct Tao{

long long int x,y;

long long int sum;

};

Tao tao[3600010];

int t=0;

void input()

{

int k;

scanf("%d%d%d%d",&n,&m,&tim,&tili);

for(int i=1;i<=n;++i)//x

for(int
j=1;j<=m;++j)//y

{

scanf("%d",&k);

if(k!=0)

{

++t;

tao[t].x=i;

tao[t].y=j;

tao[t].sum=k;

}

}

int p=0;

for(int i=1;i<=n;++i)

for(int j=1;j<=m;++j)

{

scanf("%d",&k);//ci shu

if(k!=0&&tao[p+1].sum!=0)

{

p++;

for(int i=1;i<=k;i*=2)

{

if(i==1)

{

tao[p].x=tao[p].x*i;

tao[p].y=tao[p].y*i;

tao[p].sum=tao[p].sum*i;

k-=i;

continue;

}

++t;

tao[t].x=tao[p].x*i;

tao[t].y=tao[p].y*i;

tao[t].sum=tao[p].sum*i;

k-=i;

}

if(k>0)

{

++t;

tao[t].x=tao[p].x*k;

tao[t].y=tao[p].y*k;

tao[t].sum=tao[p].sum*k;

}

}

}

}

int main()

{

input();

int VV=min(tim,tili-1);

for(int i=1;i<=t;++i)

for(int
j=VV;j>=(tao[i].x+tao[i].y)*2;--j)

f[j]=max(f[j],f[j-2*tao[i].x-2*tao[i].y]+tao[i].sum);

printf("%d\n",f[VV]);

return 0;

}

方法三:没过,不分解,01背包再加一层循环
代码:

#include< iostream >

#include< cstdio >

using namespace std;

int taosum=0,n,m,tim,tili;

long long int f[1001];

struct Tao{

long long int x,y;

long long int sum,cs;

};

Tao tao[3600010];

int t=0;

void input()

{

int k;

scanf("%d%d%d%d",&n,&m,&tim,&tili);

for(int i=1;i<=n;++i)//x

for(int
j=1;j<=m;++j)//y

{

scanf("%d",&k);

if(k!=0)

{

++t;

tao[t].x=i;

tao[t].y=j;

tao[t].sum=k;

}

}

t=0;

for(int i=1;i<=n;++i)

for(int j=1;j<=m;++j)

{

scanf("%d",&k);

if(k!=0)

{

t++;

tao[t].cs=k;

}

}

}

int main()

{

input();

for(int i=1;i<=t;++i)

for(int
l=1;l<=tao[i].cs;++l)

for(int j=min(tim,tili-1);j>=(tao[i].x+tao[i].y)*2;--j)

f[j]=max(f[j],f[j-2*tao[i].x-2*tao[i].y]+tao[i].sum);

printf("%d\n",f[min(tili-1,tim)]);

return 0;

}
正确代码:
一:
#include <
cstdio >
#include <
iostream >
using namespace
std;
int
V,n,m,T,A,amount[105][105],f[20000],value[105][105];
int main()
{

scanf("%d%d%d%d",&n,&m,&T,&A);

if(T>A-1)V=A-1;

else
V=T;
for(int
i=1;i<=n;i++)
for(int
j=1;j<=m;j++)

scanf("%d",&value[i][j]);
for(int
i=1;i<=n;i++)
for(int
j=1;j<=m;j++)

scanf("%d",&amount[i][j]);
for(int
i=1;i<=n;i++)
for(int
j=1;j<=m;j++)
for(int
k=1;k<=amount[i][j];k++)
for(int
t=V;t>=2*(i+j);t--)
if(f[t]

f[t]=f[t-2*(i+j)]+value[i][j];

printf("%d",f[V]);

return
0;
}
正确二:
#include<
iostream >
#include<
cstdio >
#include<
vector >
using namespace
std;
typedef pair<
int,int > pi;
vectorvec;
int
dp[110],a[110][110];
int main(){
int
m,n;cin>>m>>n;
int V,temp;

cin>>V>>temp;

V=min(V,temp-1);
for(int
i=1;i<=m;i++)
for(int
j=1;j<=n;j++){

cin>>a[i][j];
}
for(int
i=1;i<=m;i++){
for(int
j=1;j<=n;j++){

cin>>temp;

if(temp!=0){
int t=1;

while(temp>t){

vec.push_back(pi(t*a[i][j],2*t*(i+j)));
temp-=t;

t=t<<1;
}

if(temp>0)

vec.push_back(pi(temp*a[i][j],2*temp*(i+j)));
}
}
}
for(int
i=0;i
int
tea=vec[i].first;
int
teb=vec[i].second;
for(int
j=V;j>=teb;j--){

dp[j]=max(dp[j],dp[j-teb]+tea);
}
}

cout<<dp[V];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: