UVA 11729(Commando War-按执行时间贪心)




G

Commando War

Input: Standard Input

Output: Standard Output

 

 

“Waiting for orders we held in the wood, word from the front never came

By evening the sound of the gunfire was miles away

Ah softly we moved through the shadows, slip away through the trees

Crossing their lines in the mists in the fields on our hands and our knees

And all that I ever, was able to see

The fire in the air, glowing red, silhouetting the smoke on the breeze”

 

There is a war and it doesn't look very promising for your country. Now it's time to act. You have a commando squad at your disposal and planning an ambush on an important enemy camp located nearby. You have soldiers in your squad. In
your master-plan, every single soldier has a unique responsibility and you don't want any of your soldier to know the plan for other soldiers so that everyone can focus on his task only. In order to enforce this, you brief every individual soldier about his
tasks separately and just before sending him to the battlefield. You know that every single soldier needs a certain amount of time to execute his job. You also know very clearly how much time you need to brief every single soldier. Being anxious to finish
the total operation as soon as possible, you need to find an order of briefing your soldiers that will minimize the time necessary for all the soldiers to complete their tasks. You may assume that, no soldier has a plan that depends on the tasks of his fellows.
In other words, once a soldier  begins a task, he can finish it without the necessity of pausing in between.

 

Input

 

There will be multiple test cases in the input file. Every test case starts with an integer N (1<=N<=1000), denoting the number of soldiers. Each of the following N lines describe a soldier with two integers B (1<=B<=10000) J
(1<=J<=10000)
seconds are needed to brief the soldier while completing his job needs seconds. The end of input will be denoted by a case with N =0 . This case should not be processed.

 

Output

 

For each test case, print a line in the format, “Case X: Y”, where X is the case number & Y is the total number of seconds counted from the start of your first briefing till the completion of all jobs.

 

Sample Input                                               Output for Sample Input

3

2 5

3 2

2 1

3

3 3

4 4

5 5

0

Case 1: 8

Case 2: 15

 


Problem Setter: Mohammad Mahmudur Rahman, Special Thanks: Manzurur Rahman Khan


按照执行时间排序,贪心

可以画图验证。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
#define MAXN (1000+10)
#define MAXBi (10000+10)
#define MAXJi (10000+10)
struct arr
{
	int a,b;
	friend bool operator<(arr a,arr b){return a.b>b.b;	}
}a[MAXN];
int n;
int main()
{
	int t=1;
	while (scanf("%d",&n)!=EOF&&n)
	{
		for (int i=1;i<=n;i++) scanf("%d%d",&a[i].a,&a[i].b);
		sort(a+1,a+n+1);
		int p=0,ans=0;
		for (int i=1;i<=n;i++)
		{
			p+=a[i].a;
			ans=max(ans,p+a[i].b);
		}
		printf("Case %d: %dn",t++,ans);
	}
	return 0;
}

回文子串对(扩展kmp-kmp与回文子串)

Problem 1 回文子串对(manacher.cpp/c/pas)

【题目描述】

给定一长度为n的小写字母串,求有多少对回文子串,它们的交集非空。

一对回文子串的交集非空:[a,b]、[c,d](a≠c或b≠d)为2个回文子串,且[a,b]∩[c,d]≠∅。

【输入格式】

第一行一个整数n表示串长。

第二行长度为n的小写字母串。

【输出格式】

输出一个整数表示答案,答案对1000000007取模。

【样例输入】

4

babb

【样例输出】

6

【数据范围】

对于30%的数据,n<=1000

另有10%的数据,串里仅含一种字母。

对于100%的数据,n<=2*10^6

 

找到最前面的max(r[j]+j),映射过去

设r[i]表示以i点为中心点的最长回文子串

则如图:



#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
#define F (1000000007)
#define MAXN (2000000+10)
using namespace std;
long long r[MAXN],n,L[MAXN][2],R[MAXN][3];
char s[MAXN];
int main()
{
	freopen("manacher.in","r",stdin);
	freopen("manacher.out","w",stdout);
	scanf("%d%s",&n,s+1);
	memset(r,0,sizeof(r));
	memset(L,0,sizeof(L));
	memset(R,0,sizeof(R));
	int j=0;
	for (int i=1;i<=n;i++)
	{
		if (r[j]+j>i) r[i]=min(r[j-(i-j)],j+r[j]-i);
		while (i-r[i]>1&&i+r[i]<n&&s[i-r[i]-1]==s[i+r[i]+1]) r[i]++;
		if (r[i]+i>r[j]+j) j=i;
		L[i-r[i]][0]+=1;
		L[i+1][0]-=1;
		R[i][0]++;
		R[i+r[i]+1][0]--;
	}
//	for (int i=1;i<=n;i++) cout<<r[i]<<' ';cout<<endl;
	j=0;memset(r,0,sizeof(r));
	for (int i=1;i<n;i++)
	{
		if (r[j]+j>i) r[i]=min(r[j-(i-j)],j+r[j]-i);
		while (i-r[i]>0&&i+r[i]<=n&&s[i+1-r[i]-1]==s[i+r[i]+1]) r[i]++;
		if (r[i]+i>r[j]+j) j=i;
		L[i+1-r[i]][0]+=1;
		L[i+1][0]-=1;
		R[i+1][0]++;
		R[i+r[i]+1][0]--;
	}
/*
	for (int i=1;i<=n;i++) cout<<L[i][0]<<' ';cout<<endl;
	for (int i=1;i<=n;i++) cout<<R[i][0]<<' ';cout<<endl;
*/
	for (int i=1;i<=n;i++) L[i][1]=L[i][0]+L[i-1][1];
	for (int j=1;j<=2;j++)
		for (int i=1;i<=n;i++)
			R[i][j]=R[i-1][j]+R[i][j-1];
	long long ans=0;
	for (int i=1;i<=n;i++)
		ans=(ans+L[i][1]*R[i-1][2])%F;
	long long tot=0;
	if (R[n][2]%2) tot=(((R[n][2]-1)/2)%F)*((R[n][2])%F)%F;
	else tot=(((R[n][2])/2)%F)*((R[n][2]-1)%F)%F;
//	cout<<tot<<' '<<ans<<endl;

	cout<<((tot-ans+F)%F)<<endl;
	return 0;
}




放球游戏(a^b博弈)

Problem 3 放球游戏(ball.cpp/c/pas)

【题目描述】

     Stas和Masha发明了一个游戏。游戏道具是a个两两不同的箱子和b个两两不同的皮球,Stas和Masha轮流操作,且每次操作新增一个完全不同的箱子或皮球。如果Stas或Masha操作了以后,把b个皮球放进a个箱子的方案数不小于n,那么这个人就会输掉。所有箱子和皮球都是不同的,可以有空的箱子。
  如果第一回合由Stas先操作,且Stas和Masha都按照最优策略进行游戏,那么是否会打平?如果不打平,谁会输??

【输入格式】

输入的第一行包含三个正整数a,b,n。

【输出格式】

如果Stas会输,输出'Stas'(不要输出引号);如果Masha会输,输出'Masha';   如果游戏会打平(也就是不结束),输出'Missing'。

【样例输入】

样例一:2 2 10

样例二:5 5 16808

样例三:3 1 4

样例四:1 4 10

 

【样例输出】

样例一:Masha

样例二:Masha

样例三:Stas

样例四:Missing

【数据范围】

对于10%的数据,n不超过10;
    对于30%的数据,n不超过10000。

对于100%的数据,1≤a≤10,000, 1≤b≤30, 2≤n≤1,000,000,000, a^b<n

博弈a^b=n

把a>1的所用情况记忆化(情况数少)

唯一平局的情况是

a=1 b=x 

(a+1)^b爆 

还有一种是

1^x 2^x爆 判奇偶

其实不记忆化也能过(汗-_-)。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
#define MAXN (1000000000)
#define MAXA (10000+10)
#define MAXB (30+10)
long long a,b,n;
bool pow2(long long a,long long b)
{
	long long ans=1;
	for(int i=1;i<=b;i++)
	{
		ans*=a;
		if (ans>=n) return 0;
	}
	return 1;
}
int dfs(long long a,long long b) //a,b状态保证合法 0 Miss 1 Win -1 Lost
{
	if (a==1&&!pow2(a+1,b)) return 0;
	int flag=-1;
	if (a==1)
	{
		if (pow2(a+1,b)) flag=max(-dfs(a+1,b),flag);
		if (flag==1) return 1;
		if (pow2(a,b+1)) flag=max(-dfs(a,b+1),flag);
		return flag;
	}
	else
	{
		if (pow2(a,b+1)) flag=max(-dfs(a,b+1),flag);
		if (flag==1) return 1;
		if (pow2(a+1,b)) flag=max(-dfs(a+1,b),flag);
		return flag;
	}
}
int main()
{
	freopen("ball.in","r",stdin);
	freopen("ball.out","w",stdout);
	scanf("%d%d%d",&a,&b,&n);
	/*
	if (a==1&&!pow2(a+1,b))
	{

		return 0;
	}
	else if (b==1&&!dfs(a,b+1))
	{

	}
	*/
	int p=dfs(a,b);
	if (p==0) printf("Missingn");
	else if (p==-1) printf("Stasn");
	else printf("Mashan");
	return 0;
}

BZOJ 1502([NOI2005]月下柠檬树-Simpson积分)

1502: [NOI2005]月下柠檬树

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 250  Solved: 148
[Submit][Status][Discuss]

Description

李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树旁,独自思索着人生的哲理。
李哲是一个喜爱思考的孩子,当他看到在月光的照射下柠檬树投在地面上的影子是如此的清晰,马上想到了一个问题:树影的面积是多大呢?
李哲知道,直接测量面积是很难的,他想用几何的方法算,因为他对这棵柠檬树的形状了解得非常清楚,而且想好了简化的方法。
李哲将整棵柠檬树分成了 n 层,由下向上依次将层编号为 1,2,...,n。从第 1到 n-1 层,每层都是一个圆台型,第 n 层(最上面一层)是圆锥型。对于圆台型,其上下底面都是水平的圆。对于相邻的两个圆台,上层的下底面和下层的上底面重合。第 n 层(最上面一层)圆锥的底面就是第 n-1 层圆台的上底面。所有的底面的圆心(包括树顶)处在同一条与地面垂直的直线上。李哲知道每一层的高度为h1,h2,...,hn,第 1 层圆台的下底面距地面的高度为 h0,以及每层的下底面的圆的半径 r1,r2,...,rn。李哲用熟知的方法测出了月亮的光线与地面的夹角为
alpha。

Input

文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度)。 第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度。 第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的圆的半径。 上述输入文件中的数据,同一行相邻的两个数之间用一个空格分隔。 输入的所有实数的小数点后可能包含1至10位有效数字。

Output

输出1个实数,表示树影的面积。四舍五入保留两位小数。

Sample Input

2 0.7853981633

10.0 10.00 10.00

4.00 5.00

Sample Output

171.97

HINT

1≤n≤500,0.3<alpha<π 2,0<hi≤100,0<ri≤100。
 10%的数据中,n=1。
30%的数据中,n≤2。
60%的数据中,n≤20。
100%的数据中,n≤500。

这题是Simpson模版题。
有一个关键是圆的公切线的求法。
首先延长圆的切线求l,再求θ,最后用相似三角形。


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define MAXN (500+10)
#define eps 1e-8
double h[MAXN],s[MAXN],r[MAXN],alpha,l1=0,r1=0;
double sqr(double x){return x*x;}
int n,size=0;
struct S
{
	double x,y,p,q;
}c[MAXN];
double f(double l)
{
	double t=0.0;
	for (int i=0;i<n;i++)
	{
		if (fabs(s[i]-l)<r[i]) t=max(t,sqrt(sqr(r[i])-sqr(s[i]-l)));
	}
	for (int i=1;i<=size;i++)
	{
		if (c[i].x<l&&l<c[i].p)	t=max(t,c[i].y+(c[i].q-c[i].y)*(l-c[i].x)/(c[i].p-c[i].x));
	}
	return t;

}
double simpson(double l,double r,double fl,double fmid,double fr)
{
	return (fl+4*fmid+fr)*(r-l)/6;
}
double rsimpson(double l,double r,double fl,double fmid,double fr)
{
	double m=(l+r)/2;
	double p=f((l+m)/2),q=f((m+r)/2);
	double x=simpson(l,r,fl,fmid,fr),y=simpson(l,m,fl,p,fmid),z=simpson(m,r,fmid,q,fr);
	if (fabs(x-y-z)<eps)
		return y+z;
	return rsimpson(l,m,fl,p,fmid)+rsimpson(m,r,fmid,q,fr);
}
int main()
{
	scanf("%d%lf",&n,&alpha);
	alpha=1/tan(alpha);
	for (int i=0;i<=n;i++)
	{
		scanf("%lf",&h[i]);
		if (i) h[i]+=h[i-1];
		s[i]=h[i]*alpha;
	}
	for (int i=0;i<n;i++)
	{
		scanf("%lf",&r[i]);
		l1=min(l1,s[i]-r[i]);
		r1=max(r1,s[i]+r[i]);
	}
	r[n]=0;
	for (int i=0;i<n;i++)
	{
		double d=s[i+1]-s[i];
		if (d>fabs(r[i]-r[i+1]))
		{
			c[++size].x=s[i]-r[i]*(r[i+1]-r[i])/d;
			c[size].y=sqrt(sqr(r[i])-sqr(c[size].x-s[i]));
			c[size].p=s[i+1]-r[i+1]*(r[i+1]-r[i])/d;
			c[size].q=sqrt(sqr(r[i+1])-sqr(c[size].p-s[i+1]));
		}
	}
	r1=max(r1,s[n]);
	printf("%.2lf",2*rsimpson(l1,r1,0,f((l1+r1)/2),0));
	return 0;
}