BUAA集训队选拔赛

额。

这几天复习期末考试

话说这个期末考试真是无聊。。。好在还有最后一门计组了(如果面向对象大作业的队友靠谱能在我不在的时候完成的话)。。

计组的讲义都快倒背如流了。。。

不过。。。

不过再坚持两天应该就能拿到八千块了。。。

就可以入个单反了。。。。

虽说这个选拔赛明天才结束

不过看大家已经不再A题了。。

索性今晚也看不下去计组

就总结一下这次选拔赛吧。。

20题。。

只A了13道

学了好多新东西

一道一道来看吧


L. garlic and zombies

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

This problem is recommended for ACM newcomers. huangshenno1 is playing the famous game Plants VS Zombies and he is so boring that he puts garlic onto every grid of the garden. At this time, there happen to be a zombie coming from the middle path. Initially, the zombie is in the nth column but there is a car in the 0th column of every path. A car will beat the zombie as soon as the zombie meets it. Assume that when a zombie meet a garlic, it will either go up-left or go down-left and both possibility is 50%(See the picture, but it will never go out of the garden). huangshenno1 wants to know the possibility of the cars from path 1 to path 5 to beat this zombie if there are n columns.

Input

There are multiple test cases.

For each test case there is only one line with a single integer n indicating the number of columns. (0<=n<=10000)

Output

For each test case output one line five numbers indicating possibilities of the cars from path 1 to path 5 to beat this zombie, each number with 2 digits after the decimal point.

Sample Input

1
9

Sample Output

0.00 0.50 0.00 0.50 0.00
0.00 0.50 0.00 0.50 0.00

Author

huangshenno1 
额。。。当时懒得去推了。。直接找规律了。。

/*
脑残了我艹。。。
*/
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
	int n;
	while(cin>>n)
	{
		if(n==0)
		{
			printf("0.00 0.00 1.00 0.00 0.00\n");
		}
		else if(n%2)
		{
			printf("0.00 0.50 0.00 0.50 0.00\n");
		}
		else
		{
			printf("0.25 0.00 0.50 0.00 0.25\n");
		}
	}
//	system("pause");
	return 0;
}
/*
附递推代码
#include <cstdio>
#include <cstring>

const int N=10000;
int n;
double dp[N+5][5];

int main()
{
    memset(dp,0,sizeof(dp));
    dp[0][2]=1;
    for (int i=0;i<N;i++)
    {
        dp[i+1][1]+=dp[i][0];
        for (int j=1;j<=3;j++)
        {
            dp[i+1][j-1]+=dp[i][j]*0.5;
            dp[i+1][j+1]+=dp[i][j]*0.5;
        }
        dp[i+1][3]+=dp[i][4];
    }

    while (scanf("%d",&n)==1)
    {
        for (int i=0;i<5;i++)
            printf("%.2lf ",dp[n][i]);
        printf("\n");
    }
    return 0;
}
*/
 

后来找了递推的代码,其实就是很简单用一个二维数组模拟一下就好


E. For Short

1000ms
1000ms
65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Have you ever been annoyed when someone uses incomprehensible abbreviations, such as AFAIK, ASAP, FYI, GTSY, IYKWIM, KIT, LOL, LTNS, PM, PS, SYS, TA, WB? Are you always trying hard to understand them? Now it is time for striking back!

Even more, you are going to shorten the whole sentences instead of phrases. For example, the previous sentence can be "EM,YAGTSTWSIOP." for short. Thus, you are able to shout proudly: "Ha-ha, can anyone understand me? Do not speak abbreviations to me anymore, or I will use these sentences against you!"

As a man of principle, you decide to apply these rules during sentences shortening:

  1. A sentence is a line contains printable characters (From ASCII codes 32 to 126) only, including letters, digits, and punctuation marks and so on.

  2. A word is a substring of sentence which only consists of letters, and any characters adjacent to the word are not letters.

  3. A word is replaced by the uppercase of the beginning letter of it for short.

  4. Other characters except spaces are remained. Spaces are deleted.

Now you are trying to rewrite these given sentences for short.

Input

The first line contains an integer T (1 ≤ T ≤ 20) -- the number of test cases.

Each test case contains a legal sentence in a single line. The length of a sentence is less than 1000 characters.

Output

For each test case, output only one line -- the corresponding "sentence" after shortened.

Sample Input

1
Even more, you are going to shorten the whole sentences instead of phrases.

Sample Output

EM,YAGTSTWSIOP.		
这种字符串模拟题认真一点1A还是很轻松的

/*
签到题
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int main()
{
	int T;
	cin>>T;
	getchar();
	while(T--)
	{
		char ch;
		int flag=1;
		while((ch=getchar())!='\n')
		{
			if(isalpha(ch))
			{
				if(flag)
				{
					printf("%c",toupper(ch));
					flag=0;
				}
				else
				{
					continue;
				}
			}
			else if(ch!=' ')
			{
			//	cout<<"hee"<<endl;
				flag=1;
				cout<<ch;
			}
			else
			{
				flag=1;
				continue;
			}
		}
		cout<<endl;
	}
//	system("pause");
	return 0;
}
		
		

C. Keine's Problem

1000ms
1000ms
65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

In Gensokyo, Keine is a teacher in Human Village. Since there are many naughty students in her class, Keine keeps a log of all in/out behaviors of all students, in chronological order.

Following is a part of an example log:

Cirno in
Rumia in
Cirno out
Rumia out

One day, Keine found that the log had been damaged. All the names of students were lost. Keine could remember that some of the records were relevant. Record u and record v are considered relevant if and only if:

  1. Record u and v are of the same student;

  2. Record u is 'I' and record v is 'O';

  3. Record u is before record v;

  4. No other record between record u and record v is of this student.

For example, the first record and the third record in the example log are relevant, since it was a log of Cirno entering and then exiting. However, there are still many possibilities for the whole log. Keine wants to know how many possible versions are there for the damaged log.

Notice that the classroom was empty at both the beginning and the ending of the log.

Input

The first line contains an integer T (1 ≤ T ≤ 1 000) -- the number of test cases.

For each test case:
The first line contains three integers: n, m, k. n (1 ≤ n ≤ 100 000) is the length of the log. m (1 ≤ m ≤ n/2) is the number of relevant pairs that Keine could remember. k (1 ≤ k ≤ 50) is the number of students who may appear in the log.
The second line contains a string, which only consists of 'I' and 'O', indicates the in/out behaviors in the log.
For next m lines, each line contains two integers u and v (u < v), indicate that the u-th and the v-th records are relevant. The u-th record must be 'I' and the v-th record must be 'O'.

Output

For each test case, output only an integer in a single line - the number of possible versions of the log, modulo (1 000 000 000+7).

Sample Input

3
8 2 3
IIOIOIOO
1 3
4 5
8 2 3
IIOOIOIO
2 3
5 6
6 2 3
IOIOIO
1 2
3 4

Sample Output

48
54
27

/*
其实就是乘法原理,模拟每次乘法,in和out分别为进入和出去的学生数
*/
/*
TT...
木有用long long wa了3次。。
*/
 
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
int mark[100005];
int main()
{
	int T;
	int n,m,k;
	scanf("%d",&T);
	while(T--)
	{
		memset(mark,0,sizeof(mark));
		scanf("%d%d%d",&n,&m,&k);
		char s[100005];
		scanf("%s",s);
		int in=k;
		int out=0;
		for(int i=0;i<m;i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			mark[x]=mark[y]=1;//有log学生 
		}
		long long ans=1;
		for(int i=1;i<=n;i++)
		{
			if(s[i-1]=='I')
			{
				ans=ans*in%1000000007;
				if(!mark[i])
				{
					out++;
				}
				in--;
			}
			else if(s[i-1]=='O')
			{
				if(!mark[i])
				{
					ans=ans*out%1000000007;
					out--;
				}
				in++;
			}
		}
		printf("%d\n",ans%1000000007);
	}
//	system("pause");
	return 0;
}

J. Miku's Boxes

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

When Miku cleans up the warehouse, She finds some boxes. All the boxes are cube, and the width of the i-th box is Ci=2^ki. Now, Miku prepares to throw these boxes away, but throwing them one by one is terrible, so she decides to put all boxes into a big box and throws it. Miku finds that only when box A's width is less than box B's, A can be put into B, and 8 boxes which width is 2^(k-1) can be put into 1 box which width is 2^k particular.

Now, please help Miku calculate how big of a box she needs to put all boxes into.

(If the biggest boxes of these boxes can meet the conditions, Miku will use this box, otherwise she will make a new box. Details please refer to the Sample Input.)

Input

The first line of input T is the number of test case.

There are three lines of each test case.

First, a integers n, means Miku find n different boxes.( 0 < n <= 50000)

Second, n intergers, k1, k2 ... kn, and ki means the i-th different box's width is 2^ki(0<=ki<=50000).

Third, n intergers, m1, m2 ... mn, and mi means the number of the i-th different box (1<=mi<=10000).

Output

For each test case output a interger K means the box's width is 2^K which Miku needs.

Sample Input

2
1
0
8
2
0 1
8 1

Sample Output

1
1

Hint

In test 1,Miku make a new box of 1 width.

In test 2,Miku use the 1 width's box her find in warehouse.

Author

qw4990



/*
简单贪心
k+1的盒子能盛8个k的盒子
从小到大排序后模拟即可
*/
#include<iostream>
#include<algorithm>
using namespace std;
struct box
{
	int len;
	int cnt;
}b[50005];
bool cmp(const box &x,const box &y)
{
	return x.len<y.len;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>b[i].len;
		}
		for(int i=1;i<=n;i++)
		{
			cin>>b[i].cnt;
		}
		sort(b+1,b+n+1,cmp);
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			int needlen=b[i].len;
			int needcnt=1;
			while(1)
			{
				if(needcnt>=b[i].cnt)
				{
					break;
				}
				needcnt=needcnt*8;
				needlen++;
			}
			ans=max(ans,needlen);
		}
		cout<<ans<<endl;
	}
//	system("pause");
	return 0;
}

O. The best trade path

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

Businessman is uesed to establishing trade-path between different cities in order to get a stable income(In this problem, a trade-path is a set of roads starting at a city and ending at the same city which should go through at least one other city.)And the long-time cargo transportation is often accompanied by great risk.

Given a map of this region and the time from some city to another city, please help businessman find the trade-path which takes the least time.

Input

There are several test cases. The first line is the number of cases.

For each test case the first line contains two integer n,m, (1<=n<=100,0<=m<=10000) which denote the number of cities and road (directed road). The following m lines contains three integer ai,bi,di which means that It takes di time from the city ai to the city bi. (1<=ai,bi<=n,di<=1000000).

Output

For each case, print the time of the shortest trade-route at the beginning of a new line. If there is no legal trade-route in the map, print -1.

Sample Input

3
5 10
1 2 10
1 3 5
2 3 2
2 4 1
3 2 3
3 4 9
3 5 2
4 5 4
5 1 7
5 4 6
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50
4 5
1 2 10
1 3 20
3 4 10
2 4 5
1 4 50

Sample Output

5
65
-1

Hint

For the sample input 1, the solution is {2->3->2};

For the sample input 2, the solution is {1->2->4->1};

But for the sample input 3, there is no solution.

Author

Shell 

/*
floyd模版题
输出最短自环就好
*/
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int map[105][105];
int n,m;
void getmap()
{
	memset(map,INF,sizeof(map));
	for(int i=1;i<=m;i++)
	{
		int x,y,len;
		cin>>x>>y>>len;
		map[x][y]=min(map[x][y],len);
	}
}
void floyd()
{
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
			}
		}
	}
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		getmap();
		floyd();
		int ans=INF;
		for(int i=1;i<=n;i++)
		{
			ans=min(ans,map[i][i]);
		}
		if(ans==INF)
		{
			cout<<"-1"<<endl;
		}
		else
		{
			cout<<ans<<endl;
		}
	}
//	system("pause");
	return 0;
}

G. Bomb!

2000ms
2000ms
65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

You have some land mines laid in a forest. Each of them has the same blast radius. If one explodes, then all the land mines within the blast radius will also explode. Actually, this causes a chain reaction.

There is a target you want to destroy. Unfortunately, only the land mine No 1 can be remotely controlled. You expect that the target would be bombed after blowing up the land mine No 1.

Now you want to know: to achieve the expectation, what is the minimum blast radius?

Input

The first line contains an integer T (1 ≤ T ≤ 10) -- the number of test cases.

For each test case:
The first line contains two integers tx and ty, indicate the coordinate of the target.
The second line contains an integer n (1 ≤ n ≤ 500), indicates the number of land mines.
Then follows n lines, each of them contains two integers, indicate the coordinate of one land mine. The first one of them is the land mine No 1.

The absolute values of all the integers above are less than or equal to 1 000 000.

Output

For each test case, output only one real number in a single line -- the minimum blast radius, rounded to 2 decimal places.

Sample Input

1
25 10
4
0 0
10 0
20 10
25 0

Sample Output

14.14

/*
变种二分搜索
不断精确查找最合适半径
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
	long long x;
	long long y;
}p[505];
queue<int>q;
int visit[505];
long long map[505][505];
int n;
long long left;
long long mid;
long long right;
int bfs()
{
	memset(visit,0,sizeof(visit));
	while(!q.empty())
	{
		q.pop();
	}
	int s=1;
	visit[s]=1;
	q.push(s);
	while(!q.empty())
	{
		s=q.front();
		q.pop();
		for(int i=0;i<=n;i++)
		{
			if(!visit[i]&&map[s][i]<=mid)
			{
				visit[i]=1;
				q.push(i);
			}
		}
	}
	return visit[0];
}
	
	
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>p[0].x>>p[0].y;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>p[i].x>>p[i].y;
		}
		long long right=0;
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=n;j++)
			{
				map[i][j]=(p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y);
				right=max(right,map[i][j]);
			}
		}
		long long left=0;
		while(left<right)
		{
			mid=(left+right)/2;
			if(bfs())
			{
				right=mid-1;
			}
			else
			{
				left=mid+1;
			}
		}
		mid=(left+right)/2;
		double ans=sqrt((double)mid);
		printf("%.2lf\n",ans);
	}
//	system("pause");
	return 0;
}
		
		
		

P. Alleria

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

Recently,Zearom32 is lost in a game called DOTA(Defense of the Ancients).And he loves a hero called Alleria in the game.he believes that this hero is the most elegant and strong hero among all heros.Alleria has a skill called Shackleshot.She will shoot an arrow with the strength of wind magic to the target.If there are trees in the certain range beside the extension line connected Alleria and the target,the target will be nailed to the tree so that he will be stunned for a long time.otherwise,the target will be just stunned for a short time which makes no difference.Zearom32 knows that the point to control Alleria perfectly is to make Shackleshot stun the enemy hero for a long time.But the judgement of whether one shoot can make it is very complex so that Zearom32 hopes that you can help him。

The judgement of Shackleshot is as below:
area 1:The fan-shaped region around the 25°beside the extension line conneted Alleria and the target
area 2:Square of length 50(The edge of square and the X,Y axis are parallel,Tip:the position of square will be different according to the relative position of Alleria and the target)
If there are trees in the dark red area surrounded by area 1 and area 2 ,the target will be nailed to the tree,which means that this is a successful shoot

Now we know the coordinate of Alleria,the enemy hero and only one tree,please judge that whether this shoot is successful which can stun the enemy hero for a long time.(Assuming that the controller of the enemy hero is a stupid AI so that the target will not move, but he will also not stand at the same horizontal or vertical line with Alleria) 

Input

The first line of input is a positive integer N which indicates the number of cases.(n<=100000)
The next N lines each contain six integer numbers x1,y1,x2,y2,x3,y3 which indicate the coordinate of Alleria,the enemy hero and the tree in proper order.
(-10000<=x1,y1,x2,y2,x3,y3<=10000 and any two of these points will not be the same)

Output

For each case,if the shoot is a successful one,print "YES" or else print "NO"

Sample Input

3
1 -1 0 0 -50 50
1 0 -1 1 -5 4
1 -1 -2 3 -3 1

Sample Output

YES
YES
NO

Author

Koye


话说独立解决计算几何好激动啊。。。

/*
向量点乘判断cos角度+判断点是否在矩形内
计算几何都是纸老虎
另外这题用cin会tle 
*/
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define PI 3.14159265
const double MIN=cos(25*PI/180);
using namespace std;
bool check(double x1,double y1,double x2,double y2,double x3,double y3)
{
	if((x1>x2&&y1<y2)&&(x3<x2&&y3>y2))
	{
		if((x3>=x2-50)&&(y3<=y2+50))
		{
			return true;
		}
	}
	if((x1<x2&&y1<y2)&&(x3>x2&&y3>y2))
	{
		if((x3<=x2+50)&&(y3<=y2+50))
		{
			return true;
		}
	}
	if((x1>x2&&y1>y2)&&(x3<x2&&y3<y2))
	{
		if((x3>=x2-50)&&(y3>=y2-50))
		{
			return true;
		}
	}
	if((x1<x2&&y1>y2)&&(x3>x2&&y3<y2))
	{
		if((x3<=x2+50)&&(y3>=y2-50))
		{
			return true;
		}
	}
	return false;
}
bool panduan(double x1,double y1,double x2,double y2,double x3,double y3)
{
	double len21=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
	double len32=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));
	double n32x=x3-x2;
	double n32y=y3-y2;
	double n21x=x2-x1;
	double n21y=y2-y1;
//	cout<<len21<<endl;
//	cout<<len32<<endl;
//	cout<<fabs((n21x*n32x+n21y*n32y))/(len21*len32)<<endl;
//	cout<<MIN<<endl;
	if(fabs((n21x*n32x+n21y*n32y))/(len21*len32)>=MIN)
	{
		return true;
	}
	return false;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		double x1,y1,x2,y2,x3,y3;
		scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3);
		if(check(x1,y1,x2,y2,x3,y3))
		{
			if(panduan(x1,y1,x2,y2,x3,y3))
			{
				printf("YES\n");
			}
			else
			{
				printf("NO\n");
			}
		}
		else
		{
			printf("NO\n");
		}
	}
//	system("pause");
	return 0;
}
		

A. City Metro

1000ms
1000ms
65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

In city L, a metro runs between two terminuses RG station and LF station. Every day, it runs m times for the direction from RG to LF. Now the transportation company asks you to design the timetable of them.

They provide you the metro's running time between each two neighboring stations. For each passenger who takes the metro of this direction, you are also provided her/his favorite departure station and when does she/he reach it. You can assume that the time of getting on and off the metro can be ignored.

You are told to minimize the sum of the passengers' waiting time. Please note that the timetable must ensure that every passenger can board the metro.

Input

The first line contains an integer T (1 ≤ T ≤ 10) -- the number of test cases.

For each test case:
The first line contains three integers: n, m and p (2 ≤ n ≤ 15, 1 ≤ m ≤ 50, 1 ≤ p ≤ 100). Here n is the number of stations (including the two terminuses); m is the times metro runs every day; and p is the number of passengers.
The second line contains (n-1) nonnegative integers, the i-th of them indicates the metro's running time between the i-th station and the (i+1)-th station. RG is the first station and the other stations are sequentially numbered. The sum of these integers is less than 500.
Then follows p lines, each of them contains two integers s and t (1 ≤ s ≤ n-1, 0 ≤ t ≤ 1 000), indicate a passenger’s departure station and the time she/he reaches it.

Output

For each test case, output only one integer in a single line -- the minimum sum of waiting time.

Sample Input

1
4 3 6
5 10 10
1 30
1 40
2 15
2 55
3 0
3 35

Sample Output

40

这个题不太会啊。。。

看了题解不过现在还是模模糊糊的。。。

唉。。。

集训的时候好好训练动态规划。。。

/*
dp[k][j]表示当乘客k为第j次车的最后一名乘客时的等待时间,那么
dp[k][j]=min(dp[k][j],dp[i,1<=i<k][j-1]+sigma{wait[k]-wait[t,i<t<k]}
化简即为 dp[k][j]=min(dp[k][j],dp[i][j-1]+(k-i)*wait[k]-(sumwait[k]-sumwait[i]));
*/ 
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
int dp[105][55];
int perrun[20];//相邻站点之间的时间 
int run[20];//run[i]表示i站之前的时间 
int wait[105];//wait[i]表示i乘客的等待时间 
int sumwait[105];//sumwait[i]表示前i个乘客的总共等待时间 
using namespace std;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n,m,p;
		cin>>n>>m>>p;
		memset(run,0,sizeof(run));
		memset(perrun,0,sizeof(perrun));
		for(int i=2;i<=n;i++)
		{
			cin>>perrun[i];
			run[i]=run[i-1]+perrun[i];
		}
		for(int i=1;i<=p;i++)
		{
			int s,t;
			cin>>s>>t;
			wait[i]=t-run[s];
		}
		sort(wait+1,wait+p+1);
		memset(sumwait,0,sizeof(sumwait));
		for(int i=1;i<=p;i++)
		{
			sumwait[i]=sumwait[i-1]+wait[i];
		}
		memset(dp,INF,sizeof(dp));
		dp[0][0]=0;
		for(int i=0;i<p;i++)
		{
			for(int j=1;j<=m;j++)
			{
				for(int k=i+1;k<=p;k++)
				{
					dp[k][j]=min(dp[k][j],dp[i][j-1]+(k-i)*wait[k]-(sumwait[k]-sumwait[i]));
				}
			}
		}
		cout<<dp[p][m]<<endl;
	}
//	system("pause");
	return 0;
}

Q. Water Supply Network Planning

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

Recently, the company of GUN bought a mountain land, and going to build N factories on the land. The location of every factory can be determined by a three-dimensional coordinate [x, y, h] (x, y represent the plane coordinates; h is the height).

Now, the company of GUN needs to supply water to every factory. So they built a water-supply source at [xw, yw, hw]. Every factory can get water from the water-supply source directly or from another factory which has already got water. Apparently, at most N water pipes are needed to guarantee every factory can get water. Notice: all the water that factories can get come from the water-supply source eventually. We need to know that it costs |x1 - x2| + |y1 - y2| + |h1 - h2| to buid a water pipe between [x1, y1, h1] and [x2, y2, h2]. Besides, because of some technical problem, if the height of a factory exceeds LIM, the factory must get water from the water-supply source directly (even so, the factory can also delivery water to other factories).

Our aim is to ensure that every factory have water suply and do our best to minimize the cost.

Input

Firstly, there is a integer T indicate there are T test cases. ( 0 < T <= 20)
For each case, begin with a line contain a inerger N, which is the number of factories.(1 <= N <= 500).
The next N lines, each line contain 3 integers x, y, h, indicates the factory's location.
The last line contains 4 inergers LIM, xw, yw, hw, indicate the height limit and the coordinate of the water-supply source.
(0 <= x, y, h, LIM, xw, yw, hw <= 100000)

Output

For each case, output one line, print the minimum cost.

Sample Input

2
2
3 10 7
2 5 9
10 1 20 3
2
3 4 7
2 3 6
5 3 10 2

Sample Output

24
23

Author

hanchao717 & mario


/*
变种最小生成树
prim前先进行预处理,将h>LIM的点设为访问过,
同时更新dist[]数组(只更新h<=LIM得点) 
*/
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int n; 
int map[505][505];
int used[505];
int dist[505];
int LIM;
struct node
{
	int x;
	int y;
	int h;
}p[505];
void getmap()
{
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=n;j++)
		{
			map[i][j]=map[j][i]=abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)+abs(p[i].h-p[j].h);
		}
	}
}
int prim()
{
	int i,j,iMinPath=0,MinPath,sum=0;
	memset(used,0,sizeof(used));
	for(i=0;i<=n;i++)
		dist[i]=map[0][i];
	used[0]=1;
	for(int i=1;i<=n;i++)
	{
		if(p[i].h>LIM)
		{
			used[i]=1;
			sum+=dist[i];
	//		cout<<sum<<endl;
			for(int j=0;j<=n;j++)
			{
				if(!used[j]&&dist[j]>map[i][j]&&p[j].h<=LIM)
					dist[j]=map[i][j];
			}	
		}
	}
	for(i=1;i<=n;i++)//最小生成树需要n条边 
	{
		MinPath=INF;
		for(j=0;j<=n;j++)
		{ 
			if(!used[j]&&dist[j]<MinPath)
			{
				MinPath=dist[j] ;
				iMinPath=j;
			}
		}
		if(MinPath==INF)
		{
			break;
		}
		used[iMinPath]=1;
		sum+=MinPath;
//		cout<<sum<<endl;
		for(j=0;j<=n;j++)
		{
			if(!used[j]&&dist[j]>map[iMinPath][j])
				dist[j]=map[iMinPath][j] ;
		}
	}
	return sum ;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		memset(p,0,sizeof(p));
		memset(dist,0,sizeof(dist));
		memset(map,0,sizeof(map));
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>p[i].x>>p[i].y>>p[i].h;
		}
		cin>>LIM;
		cin>>p[0].x>>p[0].y>>p[0].h;
		getmap();
		cout<<prim()<<endl;
	}
//	system("pause");
	return 0;
}

T. Windy's Job

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

Windy has N jobs, the i-th job will cost Windy Pi seconds to finish it, and will get Vi sense of achievement.
Windy want to get at least K sense of achievement, the minimum seconds Windy must pay?

Input

There are many test cases.(the number of test cases <= 150)
For each test case:
The first line contains two integers N and K.
The second line contains N integers Pi.
The third line contains N integers Vi.
There is a blank line after each test case.

1 <= N <= 40
0 <= K <= 1000000000
1 <= Pi, Vi <= 50000000

Output

For each test case output the answer on a single line.If Windy can't get at least K sense of achievement, print -1.

Sample Input

3 6
5 6 10
3 3 6

3 10
5 6 10
3 7 6

3 10
3 5 2
1 3 2

Sample Output

10
11
-1

Author

windy7926778

练习深搜(还需要练习)

/*
深搜注意剪枝
先将job[]按achievement从大到小排序
深搜,同时用tempp标记目前的p
因为achievement从大到小排列,若p<tempp,则分别搜索加入和不加入该job
否则,只搜索不加入该job即可 
*/ 
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
	int p;
	int v;
}job[45];
int n,k,ans1;
int cost,value;
bool cmp(const node &a,const node &b)
{
	return a.v>b.v;
}
void dfs(int index,int ans,int has,int left,int tempp)
{
	if(index>n)
	{
		return ;
	}
	if(ans>=ans1)//无需继续搜索 
	{
		return ;
	}
	if(left+has<k)//剩余的achievement不足以满足 
	{
		return ;
	}
	if(has>=k)
	{
		ans1=min(ans,ans1);
		return ;
	}
	if(job[index].p<tempp)//若p<tempp则需要分加入和不加入两种情况搜索 
	{
		int temphas=has+job[index].v;
		int tempans=ans+job[index].p;
		int templeft=left-job[index].v;
		dfs(index+1,tempans,temphas,templeft,tempp);
	}
	dfs(index+1,ans,has,left-job[index].v,min(tempp,job[index].p));
}
int main()
{
	while(cin>>n>>k)
	{
		ans1=INF;
		cost=0;
		value=0;
		for(int i=0;i<n;i++)
		{
			cin>>job[i].p;
			cost+=job[i].p;
		}
		for(int i=0;i<n;i++)
		{
			cin>>job[i].v;
			value+=job[i].v;
		}
		if(value<k)
		{
			cout<<"-1"<<endl;
			continue;
		}
		else if(value==k)
		{
			cout<<cost<<endl;
			continue;
		}
		else
		{
			sort(job,job+n,cmp);
			for(int i=0;i<n;i++)
			{
				if(job[i].v>=k)
				{
					ans1=min(ans1,job[i].p);
				}
				else
				{
					break;
				}
			}
			dfs(0,0,0,value,INF);
			cout<<ans1<<endl;
		}
	}
//	system("pause");
	return 0;
}
	

D. Bamboo Forest of the Lost

1000ms
1000ms
65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

The bamboo forest is a magical place in Gensokyo. People always get lost in this forest because it changes frequently.

You are lost in this forest now. Fortunately, you met Mokou, who lives here. She told you that the bamboo forest consists of n areas (numbered from 1 to n) and m directed paths. Each area is switching its state circularly in a sequence of k states, and it switches to the next state (or to the first state if the current state is the last one in the sequence) after every one unit of time. The number of different states among all n areas is sk, and they are numbered from 1 to sk.

People will also lose energy in the bamboo forest. In area i, it consumes you c(i) units of energy to stay in area i for a unit time. The energy consumed when you go through path e is floor(w(e)×f(p(u,i),p(v,j))), where p(u,i) is the state of the start point u when you leave u; and p(v,j) is the state of the end point v when you arrive at v. The time consumed when you go through path e is d(e).

Now you are at area 1 of the forest. The exit of the forest is at area n. The current time is 0. All areas are at the first state in the sequence now. Please calculate the minimal energy needed to get to the exit.

Notice that all times are integers, and you cannot stay in an area for a non-integer time interval. We ensure that there is at least one path from area 1 to area n.

Input

The first line contains an integer T (1 ≤ T ≤ 10) -- the number of test cases.

For each test case:
The first line contains four integers: n, m, k, sk. 1 ≤ n ≤ 10 000, 1 ≤ m ≤ 100 000, 1 ≤ k ≤ 10, 1 ≤ sk ≤ 20.
Then follows n lines, each line contains (k+1) integers. The first integer is c(i) (1 ≤ c(i) ≤ 1 000); following k integers make up the state sequence for area i.
For next sk lines, each line contains sk real numbers. The j-th number on the i-th line is f(i,j). 1 ≤ f(i,j) ≤ 7.
And next m lines, each line contains 4 integers: u, v, w, d. They represent a directed path from area u to area v with value w and value d. 1 ≤ u,v ≤ n, 1 ≤ w ≤ 1000, 1 ≤ d ≤ 16.

Output

For each test case, output an integer in a single line, which is the minimal energy needed to get to the exit.

Sample Input

1
4 5 3 3
4 1 2 3
3 1 3 2
2 2 3 2
5 3 1 3
5.0 3.0 1.0
3.0 1.0 3.0
1.0 3.0 5.0
1 2 5 2
1 3 8 3
2 3 4 1
2 4 7 3
3 4 6 2

Sample Output

25

这个题一边学习一边做的。。

邻接表构图+拆点

好神奇的感觉

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
queue<int>q;
int Head[1000005],Tail[1000005],Next[1000005],top;
int Len[1000005];
int flag[1000005];
int dist[1000005];//distance 
int c[10005];//停在原地消耗的energy 
int state[1000005][15];
double f[25][25];
int n,m,k,sk;

    /*
	Head[]下标为u,保存弧头,Head[u]=top从u出发可以到top
	Next[]记录由弧头u(不断更新)出发能够找到的下一个点
	Tail[]记录的是弧尾点
	Len[]权
	top记录边的下标 
	*/
void addedge(int u,int v,int len)//邻接表加边,现学现卖 
{ 
	Next[top]=Head[u];      
    Head[u]=top;  
    Tail[top]=v;  
    Len[top]=len;  
    top++;  
}  
void getmap()
{
	memset(Head,-1,sizeof(Head));
	top=0;
	for(int i=0;i<n;i++)
	{
		cin>>c[i];
		for(int j=0;j<k;j++)
		{
			cin>>state[i][j];
			addedge(i*k+j,i*k+(j+1)%k,c[i]);//拆点,(j+1)%k表示循环 
		}
	}
	for(int i=0;i<sk;i++)
	{
		for(int j=0;j<sk;j++)
		{
			cin>>f[i][j];
		}
	}
	for(int i=0;i<m;i++)
	{
		int u,v,w,d;
		cin>>u>>v>>w>>d;
		for(int j=0;j<k;j++)
		{
			int tempu=(u-1)*k+j;
			int tempv=(v-1)*k+(j+d)%k;
			int templen=(int)floor(w*f[state[u-1][j]-1][state[v-1][(j+d)%k]-1]);//转化到f[][] 
			addedge(tempu,tempv,templen);
		}
	}
}
void SPFA()
{
   	while(!q.empty())
   	{
		q.pop();
	}
	int s=0;
   	memset(flag,0,sizeof(flag));
   	memset(dist,INF,sizeof(dist));
   	dist[s]=0;
   	q.push(s);
   	flag[s]=1;
   	while(!q.empty())
   	{
    	s=q.front();//出队列
       	q.pop();
       	flag[s]=0;
       	for(int i=Head[s];i!=-1;i=Next[i])
       	{
        	if(dist[Tail[i]]>dist[s]+Len[i])
           	{
            	dist[Tail[i]]=dist[s]+Len[i];
               	if(!flag[Tail[i]])
               	{
                	q.push(Tail[i]);
                   	flag[Tail[i]]=1;
               	}
           	}
       	}
   	}
   	int ans=INF;
	for(int i=0;i<k;i++)
	{
		ans=min(ans,dist[k*(n-1)+i]);//拆的图中取最大值 
	}
	cout<<ans<<endl;
}

int main()
{
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m>>k>>sk;
		getmap();
		SPFA();
	
	}
//	system("pause");
	return 0;
}

S. Moving Bricks

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

Yjx is a worker moving bricks. There is no brick in the building site initially. Every day, the workshop will transport many bricks to the building site. Yjx will choose the second lightest and the second weightiest bricks (May not only choose two bricks, for example: five bricks are weight: 1, 1, 4, 4, 3, 0. Yjx will choose three bricks of weight 1, 1 and 3.) from the new bricks and the remaining bricks to build a house.

Now you are given the weight of the bricks transported in n days, please calculate order that yjx moves every day.

Input

First line contains a single integer T indicating the number of test cases.(0 < T <= 50)

Each case contains 2*n+1 lines.
The first line contains a single integer n indicating n days.(1 <= n <= 1000)
The 2*i-th line contains a single integer m indicating the number of bricks in the i-th day.(0 <= m <= 5000)
The 1+2*i-th line contains m integers indicating the weight of each brick in the i-th day.(0 <= weight <= 10^9)

Output

Each case contain n lines.

The i-th line contain 2 integers, if you can find the weight of the second lightest and the second weightiest bricks that yjx should move in the i-th day, printf them, otherwise print -1 -1.(see the sample)

Sample Input

2
3
4
1 2 3 4
3
5 6 7
2
8 9
2
1
1
1
2

Sample Output

2 3
4 6
5 8
-1 -1
2 1

Author

yjx


这个题也是学习树状数组

/*
第一次学习树状数组 
用树状数组求区间第K小元素 
先开一个数组,其中记录某个数出现次数,每输入一个树,相当于将该数出现次数加1,
对应到树状数组中就相当于insert(t, 1),统计的时候,
可以利用树状数组的求和,既可以二分枚举,也可以利用数的二进制表示
同时用set可以消除重复元素的影响
*/
#include<iostream>
#include<vector>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define MAX 5000005
using namespace std;
int b[1005][5005];
int m[1005];
int c[MAX];
int number[MAX];
int value[MAX];
int visit[MAX];
int cnt;
int n;
set<int>s;
int lowbit(int n)
{
	return n&(-n);  
        //or return n&(n^(n-1));
}
void Modify(int n,int delta)
{
	while(n<=MAX)
	{ 
		c[n]+=delta; 
		n+=lowbit(n);
	}
}
int Sum(int n)
{
	int result=0;
	while(n!=0)
	{ 
		result+=c[n]; 
		n-=lowbit(n); 
	}
	return result;
}

int find(int k)
{  
    int cnt=0,ans=0;  
    for(int i=20;i>=0;i--)
	{  
        ans+=(1<<i);  
        if(ans>=MAX || cnt+c[ans]>=k)
			ans-=(1<<i);  
        else 
			cnt+=c[ans];  
    }  
    return ans+1;  
}  
/*
int find(int x)  
{  
    int left=1, right=MAX,mid;  
    while(left<right)
    {  
        mid=(left+right)>>1;  
        if(Sum(mid)<x)  
        {  
            left=mid+1;  
        }  
        else  
        {  
            right=mid;  
        }  
    }  
    return left;  
} */ 
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		s.clear();
		memset(c,0,sizeof(c));
		memset(visit,0,sizeof(visit));
		cnt=0;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			scanf("%d",&m[i]);
			for(int j=0;j<m[i];j++)
			{
				scanf("%d",&b[i][j]);
				s.insert(b[i][j]);//避免重复 
			}
		}
		set<int>::iterator it=s.begin();
		for(int i=1;it!=s.end();i++,it++)
		{
			number[*it]=i;//受数组大小限制,这里visit数组存的是编号 
			value[i]=*it;
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m[i];j++)
			{
				if(!visit[number[b[i][j]]])
				{
					Modify(number[b[i][j]],1);
					visit[number[b[i][j]]]=1;
					cnt++;
				}
			}
			if(cnt<2)
			{
				printf("-1 -1\n");;
			}
			else
			{
				int ans1=find(2);
				int ans2=find(cnt-1);
				printf("%d %d\n",value[ans1],value[ans2]);
				Modify(ans1,-1);
				Modify(ans2,-1);
				visit[ans1]=0;
				visit[ans2]=0;
				cnt-=2;
			}
		}
	}
//	system("pause");
	return 0;
}

K. SCU's closet

Unknown ms
Unknown ms
Unknown KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   

Description

Summer comes with the hot weather.Today xiaoL wants to take the heavy coats in her closet out and bring her T-shirts and skirts in.We have konwn that the volume of SCU's closet is V units,xiaoL has N pieces of clothing to put in,each of them needs Ai units of space.When putting the i-th clothes into the closet,she finds that she needs Bi units of space to ensure the i-th clothes will be placed well.After that,the volume of the closet will decrease by Ai.Now,She wonders whether she can move all her clothes into the closet.

Input

There are multiple test cases,for each case,the first line contains 2 integers:V,N,then followed N lines,each of them contains 2 integers Ai and Bi as descriped above.

( 0 < V < 10000, 0 < N<  1000, 0 < Ai < V, Ai <= Bi < 1000 )

Output

For each test case output "YES" if she can put all her clothes into the closet or else output "NO"

Sample Input

20 3
10 20
3 10
1 7
10 2
1 10
2 11

Sample Output

YES
NO

Author

lentty 


/*
两种排序
两种贪心 
*/
#include<iostream>
#include<algorithm>
using namespace std;
struct thing
{
	int a;
	int b;
}v[1005],v2[1005];
bool cmp(const thing &x,const thing &y)//先装需要体积大的 
{
	if(x.b==y.b)
	{
		return x.a<y.a;
	}
	else
	{
		return x.b>y.b;
	}
}
bool cmp2(const thing &x,const thing &y)//先装实际占有体积小的 
{
	if(x.a==y.a)
	{
		return x.b>y.b;
	}
	else
	{
		return x.a<y.a;
	}
}
int main()
{
	int V,N;
	while(cin>>V>>N)
	{
		for(int i=0;i<N;i++)
		{
			cin>>v[i].a>>v[i].b;
			v2[i]=v[i];
		}
		sort(v,v+N,cmp);
		sort(v2,v2+N,cmp2);
		int temp=V;
		int temp2=V;
		int flag=1;
		int flag2=1;
		for(int i=0;i<N;i++)
		{
			if(temp<v[i].b)
			{
				flag=0;
				break;
			}
			temp-=v[i].a;
		}
		for(int i=0;i<N;i++)
		{
			if(temp2<v2[i].b)
			{
				flag2=0;
				break;
			}
			temp2-=v2[i].a;
		}
		if(flag||flag2)
		{
			cout<<"YES"<<endl;
		}
		else
		{
			cout<<"NO"<<endl;
		}
	}
//	system("pause");
	return 0;
}
			

其他的题就实在一点不会了。。。

cet four那个深搜TLE之后就木有思路了。。

然后story of 206那个感觉好像可以做可是无从下手的感觉。。。看到10^18就跪了。。

其他。。。其他的还是等有实力再说吧。。。

组队小明那天说他们队缺个人。。

反正我也是打酱油的。。

暑期集训主要是为了提升实力。。。

毕竟自己离regional还有距离。。。

然后后天吧

后天计组考完之后收拾好宿舍准备搬家

然后3号微软小学者的答辩虽然自己很水。。。

可是。。

可是没准成绩这个东西也占一定比重吧。。。。。。

一切顺其自然就好


先和屎宝宝一起回趟青岛

然后回来搬到本部

开始水水的计组实验小学期+切OJ啊

acm的书自己等了好久终于从图书馆等到了

这个暑假,

感觉很不一样呢!!!


加油~!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值