2013长沙邀请赛 G - Travel in time #P

17 篇文章 0 订阅

2013长沙邀请赛 G - Travel in time

 

 题意: Bob将去在长沙旅行,给出了长沙景点的交通图,在两个节点间移动需要时间花费Li。还给出visit每个节点所要的时间花费Ci和Bob对每个节点的满意度Si,此外还有个限制,Bob每次访问的景点必须比上一次访问的景点满意度要高。问:Bob在时间限制T内,从S出发回到E,所能获得的最大满意度。

(节点可以多次经过,可以只经过不参观)

 

solve:

看到那个要求递增的限制很容易想到DP,

把所有节点(N<100)按Si递增排序,只有在访问了前面的节点才能访问后面的节点。

对于每个节点,保存剩余的时间。

f[i][j] = max(f[k][ j+dist[i][k]+c[i] ] + s[i])

i - 处理到第i个节点; j - 剩余j单位的时间;dist[i][k] - 从节点i到节点k所需要的时间

 

sad:比赛的时候,在状态数组初始化的地方出错了,一直在检查,从1个小时多点检查到最后结束都没有发现真正的问题所在。

非法状态的处理&状态初始化在这方面之前也犯过类似的错误,但是这次还是没有发现。

在这道题目上卡住,耽误了太多的时间和精力,也错过了在其他题目上突破的机会。


#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
using namespace std;
struct node
{
    int c,s,id;
    bool operator <(node temp) const
    {
        return s<temp.s;
    }
}a[200];
int dist[110][110];
int S;

void Floyd(int map[110][110],int n)
{
    memcpy(dist,map,sizeof(dist));
    for (int i = 1;i <= n;i++) dist[i][i] = 0;
    for (int k = 1;k <= n;k++)
    for (int i = 1;i <= n;i++)
    for (int j = 1;j <= n;j++)
        if (dist[i][j] > dist[i][k]+dist[k][j])
            dist[i][j] = dist[i][k] + dist[k][j];
    for (int i = 1;i <= n;i++)
        dist[0][i] = dist[S][i];
}

int main()
{
    freopen("test.txt","r",stdin);
    int W;
    cin>>W;
    for (int cas = 1;cas <= W;cas++)
    {
        int N,M,T,E;
        cin>>N>>M>>T>>S>>E;
        ++S,++E;
        for (int i = 1;i <= N;i++) scanf("%d",&a[i].c);
        for (int i = 1;i <= N;i++)
        {
            scanf("%d",&a[i].s);
            a[i].id = i;
        }
        static int map[110][110];
        memset(map,0x3f,sizeof(map));
        for (int i = 1;i <= M;i++)
        {
            int u,v,l;
            scanf("%d%d%d",&u,&v,&l);
            ++u,++v;
            if (l < map[u][v])
                map[u][v] = map[v][u]= l;
        }
        a[0].c = a[0].id = 0;
        a[0].s = -1;
        sort(a+1,a+N+1);
        Floyd(map,N);
        if (dist[S][E] > T)
        {
            printf("Case #%d:\n",cas);
            cout<<0<<endl;
            continue;
        }

        int ans = 0;
        static int f[110][310];
        ///!wrong  memset(f,0,sizeof(f));
        ///!初始化出错,没有排除掉非法状态,当时只考虑使得f[0][i](i<T)=0,这时赋值为0贬低了状态值,不会导致错误;
        ///!但是没有考虑到f[i][..](i>0),此时却上扬了状态值,这个一定会导致错误的。
        memset(f,-0x3f,sizeof(f));
        f[0][T] = 0;
        for (int i = 1;i <= N;i++)
        {
            int u = a[i].id;
            for (int j = 0;j <= T;j++)
            {
                for (int k = 0;k < i;k++) if (a[k].s < a[i].s)
                {
                    int v = a[k].id;
                    int tmp = j+dist[v][u]+a[i].c;
                    if (tmp <= T) f[i][j] = max(f[i][j],f[k][tmp]+a[i].s);
                }
                if (j >= dist[u][E]) ans = max(ans,f[i][j]);
            }
        }

        printf("Case #%d:\n",cas);
        cout<<ans<<endl;
    }
}





几组自己出的数据:

4
4 4 22 0 0
1 1 1 1 
5 7 9 12
0 1 10 
1 3 10
0 2 10
2 3 10

5 4 1 4 4
1 1 1 1 1
5 7 9 12 15
0 1 10 
1 3 10
0 2 10
2 3 10

2 1 32 0 1
1 1
10 5
0 1 10 

5 4 41 0 4
1 1 1 1 1 
5 10 15 20 25
0 1 10
1 2 10
2 3 10
3 4 10

答案:

Case #1:
14
Case #2:
15
Case #3:
15
Case #4:
25

 

 

错误:DP状态数组的初始化,非法状态的赋值错误。

f[0][T] = 0;其他的值应该是什么?其他的值可以初始化为0吗?

--! 可以,f[0][i] (i<T) 是把状态值给贬低了,不会影响最后的结果。

--!不可以,没有考虑其他的非法状态,比如f[i][T](i>0),这样会把状态值给上扬,一定会导致错误。

正确:f[0][T] = 0;f[other] = -INF;

初始化的时候,1.把合法的状态赋值为相应值;2.非法状态要么标志出来,要么赋值为不可能值。切记不要偷懒赋值为一个合法值,因为这样可能会同时贬低某些状态值和上扬某些状态值,而没有察觉。

越贴近事实就越准确

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值