UVa:10271 Chopsticks

 

想了一晚上加一上午,总算是给做出来了,还是1Y.

 

还是跟前面的几道题有些相似。

dp[i][j]表示前i个客人使用第j支与第j-1支筷子作为短筷子时的烂度。

很明显三元组中两只短筷子一定是相邻的,长筷子则不一定。

用降序做会比较好。

p[i][j]表示dp[i][j]对应状态可使用的长筷子。

 

状态转移方程:

 如果p[i-1][j-2]>1则说明可以使用第j支与第j-1支筷子作为短筷子 此时dp[i][j]=min(dp[i-1][j-2]+badness,dp[i-1][j])分别表示使用和不使用

如果不能,则dp[i][j]=dp[i-1][j] 不使用第j支与第j-1支筷子作为短筷子

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0x7f7f7f7f
using namespace std;
int ch[5005];
int dp[1005][5005];
int p[1005][5005];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int K,N;
        scanf("%d%d",&K,&N);
        K=K+8;
        memset(dp,0,sizeof(dp));
        memset(p,0,sizeof(p));
        for(int i=N; i>0; --i)
            scanf("%d",&ch[i]);
        for(int i=1; i<=N; ++i)
            p[0][i]=i;
        for(int i=1; i<=K; ++i)
        {
            for(int j=1; j<=N; ++j)
            {
                if(j<3*i-1)
                {
                    dp[i][j]=INF;
                    p[i][j]=j;
                }
                else
                {
                    if(p[i-1][j-2]>0)
                    {
                        int ld=(ch[j]-ch[j-1])*(ch[j]-ch[j-1]);
                        if(dp[i-1][j-2]+ld<dp[i][j-1])
                        {
                            dp[i][j]=dp[i-1][j-2]+ld;
                            p[i][j]=p[i-1][j-2]-1;
                        }
                        else
                        {
                            dp[i][j]=dp[i][j-1];
                            p[i][j]=p[i][j-1]+1;
                        }
                    }
                    else
                    {
                        dp[i][j]=dp[i][j-1];
                        p[i][j]=p[i][j-1]+1;
                    }
                }
            }
        }

        printf("%d\n",dp[K][N]);
    }
    return 0;
}


 

 

网上的题解和我的思路基本一致,不过没有用p[][]这个数组。代码修改后如下。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0x7f7f7f7f
using namespace std;
int ch[5005];
int dp[1005][5005];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int K,N;
        scanf("%d%d",&K,&N);
        K=K+8;
        memset(dp,0,sizeof(dp));
        for(int i=N; i>0; --i)
            scanf("%d",&ch[i]);
        for(int i=1; i<=K; ++i)
        {
            for(int j=1; j<=N; ++j)
            {
                if(j<3*i)
                    dp[i][j]=INF;
                else
                {
                        int ld=(ch[j]-ch[j-1])*(ch[j]-ch[j-1]);
                        dp[i][j]=min(dp[i-1][j-2]+ld,dp[i][j-1]);
                }
            }
        }
        printf("%d\n",dp[K][N]);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值