TYVJ 1062 合并傻子

79 篇文章 0 订阅

问题 K: TYVJ 1062 合并傻子

时间限制: 0 Sec   内存限制: 128 MB
提交: 58   解决: 20
[ 提交][ 状态][ 社区]

题目描述

在一个园形操场的四周站着N个傻子,现要将傻子有次序地合并成一堆.规定每次只能选相邻的2个傻子合并成新的一个傻子,并将新的一个傻子的RP数,记为该次合并的RP数。 (合并方法与NOI1999石子合并(本题库的沙子合并)相同,请大家参考上题合并方法) 将N个傻子合并成1个的最小RP数为RPn和最大RP数为RPx. 钟某人要合并他们,钟某人现在的RP为m,但是他要小心.... if  m> RPx  then  钟某人能很轻松的合并他们,并说出  ‘It  is  easy’ else  if  m< RPn  钟某人很担心,因为他必然由此变成一个沙茶,这时他要说:‘I  am..Sha...X’(以便提升RP) else      钟某人仍然担心自己可能成为一个沙茶,所以他要金蝉脱壳说:‘I  will  go  to  play  WarIII’

输入

数据的第1行试正整数n和m(1≤N≤100,m在longint范围之内)表示有N个傻子.第2行有N个数,分别表示合并每个傻子的所掉的RP数

输出/

输出文件仅一行包含一个句子表示钟某人说的话。

样例输入

4 -99994 4 5 9

样例输出

I am..Sha...X

提示

傻子+傻子=?

[ 提交][ 状态][ 社区]
一道动态规划题,是TYVJ 1055 沙子合并这题的变形。沙子合并详细见http://blog.csdn.net/asdfghjkl1993/article/details/19010369

这道题相当于就是用沙子合并这题的方法分别求两种情况,先算最大代价,如果小于m
则打出It is easy,如果最小代价大于m则打出I am..Sha...X,否则则打出I will go to play WarIII。

最小代价的动态方程f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1])

最大代价的动态方程f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1])
其中f[i][j]表示从i到j这个闭区间的最优解,预处理s[i]表示1到i区间内的所有沙堆之和,则s[j]-s[i-1]表示从i到j合并的代价,区间慢慢的由小变大。


#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<map>
#include<vector>
#include<stack>
#include<set>
using namespace std;
const int MAX=1010;
const int INF=1000000000;
int f[MAX][MAX];
int n,m;
int s[MAX];
int a[MAX];
void dp1()
{
    memset(f,0,sizeof(f));
	for(int i=1;i<=n-1;i++)
        f[i][i+1]=a[i]+a[i+1];
    for(int p=2;p<=n-1;p++)
        for(int i=1;i<=n-p;i++)
        {
            int j=i+p;
            f[i][j]=-INF;
            for(int k=i;k<=j-1;k++)
                f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
        }
}
void dp2()
{
    memset(f,0,sizeof(f));
	for(int i=1;i<=n-1;i++)
        f[i][i+1]=a[i]+a[i+1];
    for(int p=2;p<=n-1;p++)
        for(int i=1;i<=n-p;i++)
        {
            int j=i+p;
            f[i][j]=INF;
            for(int k=i;k<=j-1;k++)
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
        }
}
int main()
{

    while(cin>>n>>m)
    {
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            s[i]=s[i-1]+a[i];//预处理
        }
		dp1();//最大代价DP
		if(f[1][n]<m)
		{
			printf("It is easy\n");
			continue;
		}
		dp2();//最小代价DP
		if (f[1][n]>m) printf("I am..Sha...X\n");
		else printf("I will go to play WarIII\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值