LeetCode 568. Maximum Vacation Days

题意:有N个city可以travel,每个星期可以选择换一个city(或者停留在当前city),city之间可能连通也可能不连通。每个city可以travel的时间不同且每个星期不一样。一共K个星期,求最多可以travel的总天数。

这一题看起来就很像DP,状态转移是从这周到下周,一个city到下一个city,因为转移时需要判断city是否连通,所以定义状态dp[i,j]为第j个星期时travel第i个city,前j周的总的travel天数。

开始没留意到同一个city可以重复访问,如果要避免visit相同的city就要考虑之前所有的decision,所以不能只用状态代替decision sequence。o(╯□╰)o 感觉这种case只能用dfs。

状态转移是枚举下一个可以访问的city,dp[k,j+1]=max(dp[k,j+1],dp[i,j]+day[k,j+1) where k=i or k is connected to i。

注意要避免不可以到达某个city的case,所以dp[i,j]初始值是-1,如果状态转移中的dp[i,j]是-1,则直接skip。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
#include<stack>
using namespace std;

//leetcode 568. Maximum Vacation Days
int T;
int N;
int M;
int K;
class Solution {
public:
    int maxVacationDays(vector<vector<int>>& flights, vector<vector<int>>& days) {
        int N=flights.size();
        int K=days[0].size();
        int** dp=new int*[N];
        for(int i=0;i<N;i++)
        {
            dp[i]=new int[K];
        }
        for(int i=0;i<N;i++)
        {
            for(int j=0;j<K;j++)
            {
                dp[i][j]=-1;
                //cout<<dp[i][j]<<endl;
            }
        }
        dp[0][0]=days[0][0];
        for(int i=1;i<N;i++)
        {
            if(flights[0][i]==1)
            {
                dp[i][0]=days[i][0];
            }
//            else
//            {
//                dp[i][0]=-1;//no reachable
//            }
        }

        for(int j=0;j<K-1;j++)
        {
            for(int i=0;i<N;i++)
            {
                if(dp[i][j]==-1)
                {
                    continue;
                }
                for(int k=0;k<N;k++)
                {
                    if(flights[i][k]==0&&i!=k)//can stay in one city for consecutive weeks
                    {
                        continue;
                    }
                    else
                    {
                        dp[k][j+1]=max(dp[k][j+1],dp[i][j]+days[k][j+1]);
                    }
                }
            }
        }
        for(int i=0;i<N;i++)
        {
            for(int j=0;j<K;j++)
            {
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }

        int ret=0;
        for(int i=0;i<N;i++)
        {
            ret=max(ret,dp[i][K-1]);
        }
        for(int i=0;i<N;i++)
        {
            delete[] dp[i];
        }
        delete[] dp;
        return ret;
    }
};
int main()
{
    freopen("input.txt","r",stdin);
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        cin>>N>>K;
        vector<vector<int>>flights;
        vector<vector<int>>days;
        for(int i=0;i<N;i++)
        {
            flights.push_back(vector<int>());
            for(int j=0;j<N;j++)
            {
                int tmp;
                cin>>tmp;
                flights[i].push_back(tmp);
            }
        }
        for(int i=0;i<N;i++)
        {
            days.push_back(vector<int>());
            for(int j=0;j<K;j++)
            {
                int tmp;
                cin>>tmp;
                days[i].push_back(tmp);
            }
        }
        Solution sol;
        cout<<"Case #"<<ca<<": "<<sol.maxVacationDays(flights,days)<<endl;;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值