通天之潜水(洛谷 1759)

题目背景

直达通天路·小A历险记第三篇

题目描述

在猴王的帮助下,小A终于走出了这篇荒山,却发现一条波涛汹涌的河拦在了自己的面前。河面上并没有船,但好在小A有n个潜水工具。由于他还要背重重的背包,所以他只能背m重的工具,又因为他的力气并不是无限的,河却很宽,所以他只能背有v阻力的工具。但是这条河下有非常重要的数据,所以他希望能够停留的时间最久。于是他找到了你,让你告诉他方案。

输入输出格式

输入格式:

 

三个数m,v,n如题目所说

接下来n行,每行三个数ai,bi,ci分别表示所含的重力,阻力,能够支撑的时间

 

输出格式:

 

第一行一个数,表示最长的时间

接下来一行,若干个数,表示所选的物品

 

输入输出样例

输入样例#1:
100 100 3
50 60 289
40 10 116
50 50 106
输出样例#1:
405 
1 2

说明

1<=m,v<=200,n<=100

数据保证一定有方案。

若有多种方案,输出前面尽量小的方案。

/*
  第一问很容易,重点在求方案
  自己想了一个方法,设一个c[i][j]表示更新f[i][j]的最后一个元素,在更新f时顺便更新c, 
  求方案时不停往前找,感觉应该对,但错了一个点,调了很长时间发现,我想找的c[x][y],
  它的真正的f值,可能比我想要的大,此时就出现了错误。正解是用一个类似于链的东西ans,
  将两个有联系的c连了起来。 
*/
#include<cstdio>
#include<iostream>
#define M 210
#define N 110
using namespace std;
int f[M][M],ans[N][M][M],c[M][M],w1[N],w2[N],v[M],m1,m2,n;
int read()
{
    char c=getchar();int num=0,flag=1;
    while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*flag;
}
void print(int now,int a,int b)
{
    if(now<=0)return;
    print(ans[now][a][b],a-w1[now],b-w2[now]);
    printf("%d ",now);
}
int main()
{
    m1=read();m2=read();n=read();
    for(int i=1;i<=n;i++)
      w1[i]=read(),w2[i]=read(),v[i]=read();
    for(int i=1;i<=n;i++)
      for(int j=m1;j>=w1[i];j--)
        for(int k=m2;k>=w2[i];k--)
          if(f[j-w1[i]][k-w2[i]]+v[i]>f[j][k])
          {
              f[j][k]=f[j-w1[i]][k-w2[i]]+v[i];
              c[j][k]=i;
              ans[i][j][k]=c[j-w1[i]][k-w2[i]];
          }
    printf("%d\n",f[m1][m2]);
    print(c[m1][m2],m1,m2);
    return 0;
}
View Code

 

posted @ 2016-08-31 16:19  karles~  阅读(227)  评论(0编辑  收藏  举报