【USACO2000-SPRING】 滑雪

【描述】

为了奖励奶牛们良好的表现,在冬天里农夫John决定带它们出去旅行,他们要去访问USACO的主教练Rob K。因为Rob住在科罗拉多,他喜欢带奶牛们出去滑雪并需要你的帮助来决定最适合滑雪的地点。

特别的,因为他不想让奶牛们感到厌倦,他想要找到一个最好的山峰而且这个山峰要包含最多的从山顶滑到山下的路线。

你将得到一个包含了山峰和它的滑雪点的文件,你将知道滑雪的的高度,以及哪些滑雪点之间有路径相连的信息,滑雪时只能从一个高的滑雪点滑到一个低的滑雪点,且两个滑雪点之间要有路径相连。

高度最高的滑雪点为山顶,高度最低的滑雪点为山底,Rob想带尽量多的奶牛去滑雪,但是每一头奶牛都要求它的滑雪路线不能与其它奶牛完全相同,只要中途经过的路径中有一个不一样就算不同,求Rob最多能带去多少头奶牛。

【输入】

第一行包括两个数N,M, 2 <= N <= 200, 1 <= M <= 5000。分别表示滑雪点的数目及滑雪点中相连的路径数。 接下来有n个数,表示n个滑雪点的高度,每个高度在1,000,000以内,除了最后一行外,每行只有10个数。 接下来有m对数,每对数有两个数组成表示两个滑雪点之间有路径,一个滑雪点到它本身不会有路径,不同的滑雪点之间可能有多条路径。

【输出】

一个数表示Rob最多可带去滑雪的奶牛的个数

【样例输入】[复制]

4 5
500 400 300 200
1 2 
2 3 
3 4
1 4 
2 4

【样例输出】[复制]

3

居然要用高精度。。。无语了。。。调了好久。。。

dp[i][j]表示从i到j的路径数量。

#include<bits/stdc++.h>
using namespace std;
int n,m,u,v,s,t;
int a[1005],b[1005];
int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x;
}
struct BIG{
	int s[40];
	int len;
	BIG(){memset(s,0,sizeof(s));len=0;}
	friend inline BIG operator *(const BIG &a,const BIG &b){
		BIG c;
		for(int i=0;i<=a.len;++i){
			for(int j=0;j<=b.len;++j){
				c.s[i+j+1]+=a.s[i]*b.s[j]/10;
				c.s[i+j]+=a.s[i]*b.s[j]%10;
			}
		}
		for(int i=0;i<=a.len+b.len+5;i++){
			c.s[i+1]+=c.s[i]/10;
			c.s[i]%=10;
		}
		int GLF=a.len+b.len+5;
		for(;;GLF--) if((c.s[GLF])||(!GLF)) break;
		c.len=GLF;
		return c;
	}
	friend inline BIG operator +(const BIG &a,const BIG &b){
		BIG c;
		c.len=max(a.len,b.len);
		for(int i=0;i<=c.len;++i)
			c.s[i]=a.s[i]+b.s[i];
		for(int i=0;i<=c.len;++i){
			c.s[i+1]+=c.s[i]/10;
			c.s[i]%=10;
		}
		int GLF=c.len+5;
		for(;;GLF--) if((c.s[GLF])||(!GLF)) break;
		c.len=GLF;
		return c;
	}
	void print(){
		for(int i=len;i>=0;i--)
			putchar(s[i]+48);
	}
}dp[205][205];
int main(){
	BIG add;
	add.s[0]=1;
	n=read(),m=read();
	for(int i=1;i<=n;++i) b[i]=read(),a[i]=b[i];
	sort(a+1,a+n+1);
	while(m--){
		u=read(),v=read();
		u=lower_bound(a+1,a+n+1,b[u])-a;
		v=lower_bound(a+1,a+n+1,b[v])-a;
		if(u<v) swap(u,v);
		dp[u][v]=dp[u][v]+add;
	}
	for(int i=n;i>=2;--i)
		for(int j=i-2;j>=1;--j)
			for(int k=i-1;k>=j+1;--k)
				dp[i][j]=dp[i][j]+dp[i][k]*dp[k][j];
	dp[n][1].print();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值