Uva(1169)(Robotruck)

链接:https://vjudge.net/problem/UVA-1169
思路:啊啊啊啊啊啊太开心了,刚刚上一道题觉得很难,这道题我用刘汝佳上道题的思路写感觉比他的解还要简单一点,很开心。首先找出状态,我们定义dp[i][j]为当前机器人站在第i个垃圾上且已经捡起了第i个垃圾后手上的重量为j,那么我们要考虑下一步操作,回去把垃圾倒掉或者继续捡垃圾,继续捡垃圾的条件是必须捡起下一个垃圾后手上重量小于等于最大可承受重量,那么就可以分为两步进行递归,最后取最小值(用记忆式搜索会比递推好写且更好理解)
代码:

#include
#include
#include
#include
using namespace std;

struct point{
    int x,y,w;
}pp[100001];

int dp[100001][101];
int t,c,n;

int dfs(int i,int j){
    if(dp[i][j]!=0)return dp[i][j];//如果有值的话则代表已经计算过
    int& ans = dp[i][j];//引用的技巧,一定要学会,非常好用
    if(i==n){//到最后一个垃圾且已经捡起来了,则可以返回了
        ans+=pp[i].x+pp[i].y;
        return ans;
    }
    if(j+pp[i+1].w<=c){//决策一,捡下一个垃圾
    ans+=(fabs(pp[i].x-pp[i+1].x)+fabs(pp[i+1].y-pp[i].y));
    ans+=dfs(i+1,j+pp[i+1].w);
    }
    else ans = 1e9;//一定不能少这一步,不然如果不满足决策1条件此时ans为0,下一步则会被最后min给覆盖掉!!!!
//决策2,先回去再回来捡垃圾
    int sum = pp[i].x+pp[i].y+pp[i+1].x+pp[i+1].y;
    sum+=dfs(i+1,pp[i+1].w);
    ans = min(ans,sum);//取所需步数较小的一个即可
    return ans;
}

int main(){
    scanf("%d",&t);
    while(t--){
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&c,&n);
        pp[0].x = pp[0].y = pp[0].w = 0;
        for(int i=1;i<=n;++i){
            scanf("%d%d%d",&pp[i].x,&pp[i].y,&pp[i].w);
        }
    printf("%d\n",dfs(0,0));
    if(t)printf("\n");//注意输出格式,uva上格式是真的蛋疼!
    }
    return 0;
}

好吧,原来是老刘觉得我的方法要超时所以用了优化,暂时看不懂写贴上来吧


图片发自App

图片发自App

你可能感兴趣的:(Uva(1169)(Robotruck))