ACM暑期集训21

补一下昨天刷的题。

Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is planning to attend as many parties as he can. Since it's Halloween, these parties are all costume parties, Gappu always selects his costumes in such a way that it blends with his friends, that is, when he is attending the party, arranged by his comic-book-fan friends, he will go with the costume of Superman, but when the party is arranged contest-buddies, he would go with the costume of 'Chinese Postman'.

Since he is going to attend a number of parties on the Halloween night, and wear costumes accordingly, he will be changing his costumes a number of times. So, to make things a little easier, he may put on costumes one over another (that is he may wear the uniform for the postman, over the superman costume). Before each party he can take off some of the costumes, or wear a new one. That is, if he is wearing the Postman uniform over the Superman costume, and wants to go to a party in Superman costume, he can take off the Postman uniform, or he can wear a new Superman uniform. But, keep in mind that, Gappu doesn't like to wear dresses without cleaning them first, so, after taking off the Postman uniform, he cannot use that again in the Halloween night, if he needs the Postman costume again, he will have to use a new one. He can take off any number of costumes, and if he takes off k of the costumes, that will be the last k ones (e.g. if he wears costume A before costume B, to take off A, first he has to remove B).

Given the parties and the costumes, find the minimum number of costumes Gappu will need in the Halloween night.

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case starts with a line containing an integer N (1 ≤ N ≤ 100) denoting the number of parties. Next line contains Nintegers, where the ith integer ci (1 ≤ ci ≤ 100) denotes the costume he will be wearing in party i. He will attend party 1 first, then party 2, and so on.

Output

For each case, print the case number and the minimum number of required costumes.

Sample Input

2

4

1 2 1 2

7

1 2 1 1 3 2 1

 

分析:

考虑第j天穿不穿,如果穿的话那么 dp[i][j]=dp[i][j-1]+1;

如果不穿的话,那么需要有一个 k (i<=k<j),第j天和第k天穿的衣服相同,将k+1~j-1衣服套着穿后全部脱掉,那么

dp[i][j]=dp[i][k]+dp[k+1][j-1];

 

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;

int a[110];
int dp[110][110];

int main()
{
    int t;
    scanf("%d",&t);
    for(int r=1;r<=t;r++)
    {
        int n;
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                dp[i][i]=1;
            }
        for(int len=2;len<=n;len++)
            for(int i=1;i<=n;i++)
        {
            int j=i+len-1;
            dp[i][j]=dp[i][j-1]+1;
            if(j>n) break;
            for(int k=i;k<j;k++)
            {
                if(a[j]==a[k]) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j-1]);
            }
        }
        printf("Case %d: %d\n",r,dp[1][n]);
    }
    return 0;
}

 

据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成了绝技,能够毫不休息得以恒定的速度(VR m/s)一直跑。兔子一直想找机会好好得教训一下乌龟,以雪前耻。 
最近正值HDU举办50周年校庆,社会各大名流齐聚下沙,兔子也趁此机会向乌龟发起挑战。虽然乌龟深知获胜希望不大,不过迫于舆论压力,只能接受挑战。 
比赛是设在一条笔直的道路上,长度为L米,规则很简单,谁先到达终点谁就算获胜。 
无奈乌龟自从上次获胜以后,成了名龟,被一些八卦杂志称为“动物界的刘翔”,广告不断,手头也有了不少积蓄。为了能够再赢兔子,乌龟不惜花下血本买了最先进的武器——“"小飞鸽"牌电动车。这辆车在有电的情况下能够以VT1 m/s的速度“飞驰”,可惜电池容量有限,每次充满电最多只能行驶C米的距离,以后就只能用脚来蹬了,乌龟用脚蹬时的速度为VT2 m/s。更过分的是,乌龟竟然在跑道上修建了很多很多(N个)的供电站,供自己给电动车充电。其中,每次充电需要花费T秒钟的时间。当然,乌龟经过一个充电站的时候可以选择去或不去充电。 
比赛马上开始了,兔子和带着充满电的电动车的乌龟并列站在起跑线上。你的任务就是写个程序,判断乌龟用最佳的方案进军时,能不能赢了一直以恒定速度奔跑的兔子。

Input

本题目包含多组测试,请处理到文件结束。每个测试包括四行: 
第一行是一个整数L代表跑道的总长度 
第二行包含三个整数N,C,T,分别表示充电站的个数,电动车冲满电以后能行驶的距离以及每次充电所需要的时间 
第三行也是三个整数VR,VT1,VT2,分别表示兔子跑步的速度,乌龟开电动车的速度,乌龟脚蹬电动车的速度 
第四行包含了N(N<=100)个整数p1,p2...pn,分别表示各个充电站离跑道起点的距离,其中0<p1<p2<...<pn<L 
其中每个数都在32位整型范围之内。 

Output

当乌龟有可能赢的时候输出一行 “What a pity rabbit!"。否则输出一行"Good job,rabbit!";
题目数据保证不会出现乌龟和兔子同时到达的情况。

Sample Input

100
3 20 5
5 8 2
10 40 60
100
3 60 5
5 8 2
10 40 60

Sample Output

Good job,rabbit!
What a pity rabbit!

分析:
dp[i] 表示到达第i个充电站的时间

可知 dp[i]=min(dp[j]+t(j,i) )  j为上一个充电的位置 (0<=j<i)

t(j,i) 是直接从j骑到i的时间,分情况讨论即可,其中还要加上充电的时间,但j=0是不需要加充电的时间。

 

#include <iostream>
#include <cstring>
#include <stdio.h>
#include <math.h>
using namespace std;

int a[110];
double dp[110];
int main()
{
    int l,n,c,t,vr,v1,v2;
    while(~scanf("%d",&l))
    {
        scanf("%d%d%d",&n,&c,&t);
        scanf("%d%d%d",&vr,&v1,&v2);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        a[0]=0,dp[0]=0,a[n+1]=l;
        for(int i=1;i<=n+1;i++)
        {
            double mi=999999.0;
            for(int j=0;j<i;j++)
            {

                int len=a[i]-a[j];
                double time;
                if(len>c) time=(double)c/v1+(double)(len-c)/v2;
                else time=(double)len/v1;
                time+=dp[j];
                if(j) time+=t;
                if(mi>time) mi=time;
            }
            dp[i]=mi;
        }

        if((double)l/vr>dp[n+1]) printf("What a pity rabbit!\n");
        else printf("Good job,rabbit!\n");
    }
    return 0;
}

 

In the battlefield , an effective way to defeat enemies is to break their communication system. 
The information department told you that there are n enemy soldiers and their network which have n-1 communication routes can cover all of their soldiers. Information can exchange between any two soldiers by the communication routes. The number 1 soldier is the total commander and other soldiers who have only one neighbour is the frontline soldier. 
Your boss zzn ordered you to cut off some routes to make any frontline soldiers in the network cannot reflect the information they collect from the battlefield to the total commander( number 1 soldier). 
There is a kind of device who can choose some routes to cut off . But the cost (w) of any route you choose to cut off can’t be more than the device’s upper limit power. And the sum of the cost can’t be more than the device’s life m. 
Now please minimize the upper limit power of your device to finish your task. 

Input

The input consists of several test cases. 
The first line of each test case contains 2 integers: n(n<=1000)m(m<=1000000). 
Each of the following N-1 lines is of the form: 
ai bi wi 
It means there’s one route from ai to bi(undirected) and it takes wi cost to cut off the route with the device. 
(1<=ai,bi<=n,1<=wi<=1000) 
The input ends with n=m=0. 

Output

Each case should output one integer, the minimal possible upper limit power of your device to finish your task. 
If there is no way to finish the task, output -1.

Sample Input

5 5
1 3 2
1 4 3
3 5 5
4 2 6
0 0

Sample Output

3

分析:

最大值最小—— 二分

怎么检验? f

[i]为切断i的所有子孙叶子所花费的最小费用

dp[i]+=min(dp[k],dist[i][k] )    (dist[i][k] <= limit )

else dp[i] += dp[k]

 

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<string.h>
using namespace std;
const int maxn=1010;
const int inf=1e6;
int e[maxn][maxn];
int dp[maxn];
int n,m,limit;

vector<int> a[maxn];

void treedp(int node,int fa)
{
	dp[node] = 0;
	bool leaf = 1;
	for (int i = 0;i < a[node].size();++i)
	{
		int &son = a[node][i];
		if (son == fa) continue;
		leaf = 0;
		treedp(son,node);
		if (e[node][son] <= limit) dp[node] += min(dp[son],e[node][son]);
		else dp[node] += dp[son];
	}
	if (leaf) dp[node] = inf;//叶子
}


int main()
{
    while(scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        memset(e,0,sizeof(e));
        memset(a,0,sizeof(a));
        int l = 1,r = 0;
    	for (int i = 1,u,v,w;i < n;++i)
    	{
    		scanf("%d %d %d",&u,&v,&w);
    		e[u][v] = e[v][u] = w;
    		a[u].push_back(v);
    		a[v].push_back(u);
    		r = max(r,w);
		}
		int ans = -1;
	    while (l <= r)
	    {
		    int mid = (l+r)>>1;
		    limit = mid;
		    treedp(1,0);
		    if (dp[1]<=m)
		    {
			    ans = limit;
			    r = mid-1;
		    }
		    else l = mid + 1;
	    }
        printf("%d\n",ans);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值