首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 一条动态规划题目,本人程序超时,求更好的算法
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cthliao
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    • 揭帖率:
    发表于:2008-08-22 11:13:14 楼主
    虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的。但是运动员为了提高成绩难免要服用一些,super pig也是……为了不被尿检检查出来,这些药品就只能选一些不容易被发现的来服用。但是奥委会关于兴奋剂检查有很多项检查,只有尿检中各项检查数值均不超过规定指标才算成阴性(“你没服兴奋剂”),所以如何服用适量的药品使自己的水平达到最高是每个运动员困扰的问题。
    现在有n个药品(一种药只能吃一次)。尿检检查共有m个项目,服用每个药品对于每个检查项目都会提升一定的效果值,这些效果值是累加的;服用每个药品当然还会给super pig一定的水平提高值,这些效果也是累加的。现在super pig想把问题交给你来解决,他还要忙着训练。因为吃要归吃药,训练才重要。

    输入:
    第一行有两个整数n (0 <n <=200)和m (1 <=m <=5),分别表示药品数和需要检查的项目;
    第二行m个整数 v1---vm,表示检查各项目的指标(即最高不能超过的值);
    第三行到第n+2行,分别是这n个药品的资料,每行m+1个数。每行第一个数表示服用该药品所得到的水平提高值,第二到第m+1个数分别表示服用这个药品每一项的效果值(分别对应第二行的指标类型)。
    0 <= m∏(k=1)Vk <=5000000

    输出:
    一个整数,即super pig通过服这些药在不被检查出来的条件下所能得到的最高水平提高值

    时间限制1秒。

    因为小时候没读过书,看不懂输入数据的限制0 <= m∏(k=1)Vk <=5000000是什么意思,只好猜测是药的各项效果值和检查指标均 <500万。

    200个药,500万的范围,开5维背包看来是要暴机的,我就用链表玩DP。代码如下:
    C/C++ code
    #include<stdio.h> #include<stdlib.h> struct p { int w; int z[6]; struct p *next; }; int n,m,zb[6],add[201],yx[201][6]; int dp() { p *list,*base,*temp,*t,*t2; int i,j,a; list=(p *)malloc(sizeof(p)); list->w=0; for(i=1;i<=m;i++) list->z[i]=0; list->next=NULL; for(i=1;i<=n;i++) { a=1; for(j=1;j<=m;j++) if(yx[i][j]>zb[j]) { a=0; break; } if(!a) continue; base=(p *)malloc(sizeof(p)); base->w=add[i]; for(j=1;j<=m;j++) base->z[j]=yx[i][j]; base->next=NULL; t=list; while(t!=NULL) { a=1; for(j=1;j<=m;j++) if(t->z[j]+yx[i][j]>zb[j]) { a=0; break; } if(a) { temp=(p *)malloc(sizeof(p)); temp->w=t->w+add[i]; for(j=1;j<=m;j++) temp->z[j]=t->z[j]+yx[i][j]; temp->next=base; base=temp; } t2=t; t=t->next; } t2->next=base; } t=list; j=0; while(t!=NULL) { if(t->w>j) j=t->w; t=t->next; } return j; } int main() { int i,j; scanf("%d %d\n",&n,&m); for(i=1;i<=m;i++) scanf("%d ",&zb[i]); scanf("\n"); for(i=1;i<=n;i++) { scanf("%d ",&add[i]); for(j=1;j<=m;j++) scanf("%d ",&yx[i][j]); scanf("\n"); } i=dp(); printf("%d\n",i); }

    我把吃前i种药所有可能得到的提高值和m种药效都储存到链表list中,对于第i+1种药,就对list所有个结点分别加上第i+1种药的效果,m种药效相加如果不超标,就开新结点,储存新的值。因为链表不方便定位,就不判重了。
    最后搜索整个链表,取最大提高值。

    现在10个测试点,4个超时。
    40  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cthliao
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-08-22 11:15:271楼 得分:0
    上面的晕死,代码重发一遍。

    C/C++ code
    #include<stdio.h> #include<stdlib.h> struct p { int w; int z[6]; struct p *next; }; int n,m,zb[6],add[201],yx[201][6]; int dp() { p *list,*base,*temp,*t,*t2; int i,j,a; list=(p *)malloc(sizeof(p)); list->w=0; for(i=1;i<=m;i++) list->z[i]=0; list->next=NULL; for(i=1;i<=n;i++) { a=1; for(j=1;j<=m;j++) if(yx[i][j]>zb[j]) { a=0; break; } if(!a) continue; base=(p *)malloc(sizeof(p)); base->w=add[i]; for(j=1;j<=m;j++) base->z[j]=yx[i][j]; base->next=NULL; t=list; while(t!=NULL) { a=1; for(j=1;j<=m;j++) if(t->z[j]+yx[i][j]>zb[j]) { a=0; break; } if(a) { temp=(p *)malloc(sizeof(p)); temp->w=t->w+add[i]; for(j=1;j<=m;j++) temp->z[j]=t->z[j]+yx[i][j]; temp->next=base; base=temp; } t2=t; t=t->next; } t2->next=base; } t=list; j=0; while(t!=NULL) { if(t->w>j) j=t->w; t=t->next; } return j; } int main() { int i,j; scanf("%d %d\n",&n,&m); for(i=1;i<=m;i++) scanf("%d ",&zb[i]); scanf("\n"); for(i=1;i<=n;i++) { scanf("%d ",&add[i]); for(j=1;j<=m;j++) scanf("%d ",&yx[i][j]); scanf("\n"); } i=dp(); printf("%d\n",i); }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dlyme
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    • 4

    发表于:2008-08-22 12:09:482楼 得分:0
    ∏是连乘符号,五维背包没问题
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cthliao
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-08-22 12:17:133楼 得分:0
    m∏(k=1)Vk
    那这个式子是什么意思
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sjkof
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-08-22 12:38:214楼 得分:0
    m∏(k=1)Vk 即 v1*v2*...*vm
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cthliao
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-08-22 13:55:305楼 得分:0
    dlyme大哥,问题还没完啊,就算知道总乘积 <500万,但5个维每一维应该分配多少空间?难道按最坏打算分500万?
    如果用malloc开辟数组,5个维很难操作的。恐怕开数组都要N长的时间了。
    按背包问题的解法,要把每个状态都扫一遍,那么总数就是5000000*200=10亿,依然有很大的超时风险。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tailzhou
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    • 2

    发表于:2008-08-22 14:57:336楼 得分:0
    存储空间还是一维数组;但将其当作m维的数组用

    对于下标为d1,d2,...dm的元素,其对应的一维下标为(...(d1*v1+d2)*v2+...+vm)

    背包问题并不会扫到每个状态,很多状态是不会遍历到的;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ppass
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-09-04 17:07:597楼 得分:0
    - < < = > ± × ÷ ∈ ∏ ∑ ∕ √ ∝ ∞ ∟ ∠ ∣ ∥ ∧ ∨ ∩ ∪ ∫ ∮ ∴ ∵ ∶ ∷ ∽ ≈ ≌ ≒ ≠ ≡ ≤ ≥ ≦ ≧ ≮ ≯ ⊕ ⊙ ⊥ ⊿ ㏒ ㏑

    哈哈,用拼音加加, 输入"sxfh"后一次性打出~
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved