FZU 1005 Fast Food(dp)

news/2024/9/6 6:10:36

题意:输入n,k,然后输入n个数,这n个数表示距离起点的距离,现在要选取k个点,使得距离和最小。

分析:我们求的是从n个点中选取k个点使得距离最小,即dp[n][k],那么dp[n][k]为dp[n-1][k-1]+sum[n][n],dp[n-2][k-1]+sum[n-1][n],dp[n-3][k-1]+sum[n-2][n]....dp[1][k-1]+sum[2][n]之间的最小值。

其中sum[x][y]表示从x点到y点在此区间选取一个点的最短距离(如果是个数是单数的话,选取中间那个点,偶数的话选取中间两个哪个都行)

记忆化搜索:

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
using namespace std;

const int oo = 1e9;

int a[222];
int dp[222][33];
int sum[222][222];


int DFS(int n, int k)
{
    if(n<0||k<0)
        return oo;
    if(dp[n][k]!=-1)
        return dp[n][k];
    if(k>=n)
    {
        dp[n][k] = 0;
        return 0;
    }

    dp[n][k] = oo;
    for(int i=1; i<=n; i++)
    {
        dp[n][k] = min(dp[n][k], DFS(i-1, k-1)+sum[i][n]);//为前n个点建立k个点,可以由前1到n-1个点建立k-1个点推得,找到最优解。
    }
    return dp[n][k];
}

int main()
{
    int n, m;
    int kk = 1;
    while(scanf("%d%d", &n, &m), n+m)
    {
        a[0] = 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i=1; i<=n; i++)
        {
            sum[i][i] = 0;
            for(int j=i+1; j<=n; j++)
            {
                sum[i][j] = sum[i][j-1]+a[j]-a[(i+j)/2];//sum[i][j]表示在i,j之间选取一个点,消耗的最短距离(如果是单数的话,选取中间那个点,偶数的话选取中间两个哪个都行)
            }
        }
        memset(dp, -1, sizeof(dp));
        int ans = DFS(n, m);
        printf("Chain %d\n", kk++);
        printf("Total distance sum = %d\n\n", ans);
    }

    return 0;
}

dp

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
using namespace std;

const int oo = 1e9;

int a[222];
int dp[222][33];
int sum[222][222];

int main()
{
    int n, m;
    int kk = 1;
    while(scanf("%d%d", &n, &m), n+m)
    {
        a[0] = 0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i=1; i<=n; i++)
        {
            sum[i][i] = 0;
            for(int j=i+1; j<=n; j++)
            {
                sum[i][j] = sum[i][j-1]+a[j]-a[(i+j)/2];
            }
        }
        for(int i=0; i<=n; i++)
        {
            for(int j=0; j<=m; j++)
            {
                dp[i][j] = oo;
            }
        }
        dp[0][0] = 0;
        for(int i=1; i<=n; i++)
        {
            for(int k=1; k<=m; k++)
            {
                for(int j=0; j<i; j++)//此层循环和上层循环哪个在外面都可以,因为dp[i][k]只和 dp[1][k-1]到dp[i-1][k-1]之间的有关
                {
                    dp[i][k] = min(dp[i][k], dp[j][k-1]+sum[j+1][i]);//枚举从1到i-1之间的状态,进行更新dp[i][k]的值
                }
            }
        }
        printf("Chain %d\n", kk++);
        printf("Total distance sum = %d\n\n", dp[n][m]);
    }

    return 0;
}

 

转载于:https://www.cnblogs.com/mengzhong/p/5414100.html


http://www.niftyadmin.cn/n/515521.html

相关文章

C#线程池控制Semaphore

目的&#xff1a;控制线程数量执行某些代码、避免蜂拥进入 的异步执行导致系统 崩溃。 使用&#xff1a; 1. Semaphore Semaphore new Semaphore(3, 3); // 控制线程数 2. public void StatisticsDate(object store){ Semaphore.WaitOne();//进入线程池控…

C#使用MySql进行操作

1.安装Mysql&#xff08;网上教程有&#xff09; 2.创建项目webapi 3.引用dll一般在&#xff08;安装MySQL就有的没有参考&#xff1a;ASP.NET 连接MySQL数据库 详细步骤 - wusir - 博客园&#xff09;&#xff1a;C:\Program Files (x86)\MySQL\MySQL Connector Net 8.0.23\…

进度条第八周

第八周 所花时间&#xff08;包括上课&#xff09;&#xff1a; 周一&#xff1a;上午两小时上课时间&#xff0c;下午花了两小时查阅相关书籍。 周二&#xff1a;下午花了一个小时配置所需环境。 周四&#xff1a;开始开站立会议&#xff0c;录制视频花了两小时。 周五&a…

关于EF翻页查询数据库

1./// <summary> /// 翻页查询 /// </summary> /// <typeparam name"Tkey"></typeparam> /// <param name"pageSize">每页大小</param> /// <param name"pageIndex&…

判断栈的出栈顺序是否正确

一 问题描述&#xff1a; 两个数组pPush和pPop分别存储了压栈序列和出栈序列&#xff0c;如何判断出栈序列是否正确&#xff0c;假设元素不重复。 需要实现的函数&#xff1a; bool isStackOutRight(int *stackIn,int *stackOut,int length) 二 举例&#xff1a; pPush中序列为…

html指定轮动调的高度(js)

1.设置标签id&#xff1a;ChatRecordId 2.var ex document.getElementById("ChatRecordId"); ex.scrollTop ex.scrollHeight;

ssl 1763 观光旅游 环的计算

题目大意 求一个最小环 分析 在floyd的同时&#xff0c;顺便算出最小环 g[i][j]i,j之间的边长 dist:g; for k:1 to n do begin for i:1 to n do for j:i1 to n do answer:min(answer,dist[i][j]g[i][k]g[k][j]); for i:1 to n do for j:1 to n do dist[i][j]:min(dist[i][j],di…

函数封装

封装即是把抽象出的属性和对属性的操作封装在一起&#xff0c;属性被保护在内部&#xff0c;程序的其他部分只有通过被授权的操作&#xff08;如函数&#xff09;才能对属性进行操作。转载于:https://www.cnblogs.com/haimengqingyuan/p/5425333.html