GDUT 第一次组队赛 Team up! Team up! Team up!(三,dp,dfs)

这里水题就不写出来了,补一下当时比赛没能想出来的题目。
题目提交网站:
http://codeforces.com/group/NVaJtLaLjS/contest/241520
Problem A — limit 2 seconds

Millionaire

Congratulations! You were selected to take part in the TV game show Who Wants to Be a Millionaire! Like most people, you are somewhat risk-averse, so you might rather take $250,000 than a 50% chance of winning $1,000,000. On the other hand, if you happen to already be rich, then you might as well take a chance on the latter. Before appearing on the show, you want to devise a strategy to maximize the expected happiness derived from your winnings. More precisely, if your present net worth is W dollars, then winning v dollars gives you ln(1 +v/W) units of happiness. Thus, the game’s expected happiness is Pv P(v) ln(1+v/W), where P(v) is the probability that you’ll win v dollars, and the summation is taken over all possible values of v. Since happiness units are too abstract, you will be asked to measure the value of the game in dollars. That is, compute D such that a guaranteed payout of D dollars makes you as happy as a chance on the show, assuming optimal play. On the show, you will be presented with a series of questions on trivia, each associated with a prize value of vi dollars. Your analysis of past episodes reveals that if you attempt the ith question, your chances of being correct are pi After answering correctly, you may choose to continue or to quit. If you quit, you win the value of the last correctly answered question; otherwise, the game continues and you must attempt the next question. If you correctly answer all the questions, you walk away with the value of the last question. If you answer a question incorrectly, however, the game ends immediately and you win the value of the last correctly answered question that is labeled as safe, or nothing if you never solved a safe question. For example, the game in the first sample input is worth 0.5 ln(1 + 5000/4000) ≈ 0.405 units of happiness. Getting $2,000 would likewise grant ln(1 + 2000/4000) ≈ 0.405 happiness.
Input
The first line of input contains two space-separated integers n and W (1 ≤ n ≤ 10 ^ 5, 1 ≤ W ≤ 10 ^ 6).
Line i + 1 describes the ith question. It starts with a string, which is one of safe or unsafe, indicating whether the ith question is safe or not. The string is followed by a real number pi and an integer vi (0 ≤ pi ≤ 1, 1 ≤ vi < vi+1 ≤ 10^6).
Output
Print, on a single line, a $ sign immediately followed by D, rounded and displayed to exactly two decimal places. See the samples for format clarification.

Sample Input

1 4000
unsafe 0.5 5000

Sample Output

$2000.00

Sample Input

4 4000
unsafe 1 2000
safe 0.4 5000
unsafe 0.75 10000
safe 0.05 1000000

Sample Output

$2316.82

Sample Input

2 4000
safe 0.003 1
safe 0.03 10

Sample Output

$0.00
比赛的最难题。

题目大意:

。。。

#include 
using namespace std;
const int INF = 0x3f3f3f3f;
inline int read(){
    int xx = 0,ff = 1; char ch = getchar();
    while(ch <'0' || ch > '9'){
        if(ch == '-') ff = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        xx = xx * 10 + ch - '0';
        ch = getchar();
    }
    return xx * ff;
}

struct haha{
    int safe,v;
    double p;
}a[100005];
char st[10];
int n,w;
double happ[100005];
int MAX[100005];
int main(){
    while(~scanf("%d%d",&n,&w)){
        memset(MAX, 0, sizeof MAX);
        memset(happ, 0, sizeof happ);
        for(int i = 1;i <= n;i ++){
            scanf("%s",st);
            if(st[0] == 'u') a[i].safe = 0;
            else a[i].safe = 1;
            scanf("%lf",&a[i].p);
            a[i].v = read();
            if(a[i].safe)MAX[i] = max(MAX[i-1], a[i].v);
            else MAX[i] = MAX[i-1];
        }
        for(int i = n;i>=1;i--){
            happ[i] = a[i].p*max(happ[i+1],log(1.0+1.0*a[i].v/w))
                        +(1-a[i].p)*log(1.0+1.0*MAX[i-1]/w);
        }
        printf("$%.2f\n",(exp(happ[1])-1.0)*w);
    }
    return 0;
}

Problem H — limit 4 seconds

Surf

Now that you’ve come to Florida and taken up surfing, you love it! Of course, you’ve realized that if you take a particular wave, even if it’s very fun, you may miss another wave that’s just about to come that’s even more fun. Luckily, you’ve gotten excellent data for each wave that is going to come: you’ll know exactly when it will come, how many fun points you’ll earn if you take it, and how much time you’ll have to wait before taking another wave. (The wait is due to the fact that
the wave itself takes some time to ride and then you have to paddle back out to where the waves are crashing.) Obviously, given a list of waves, your goal will be to maximize the amount of fun you could have. Consider, for example, the following list of waves:
Minute Fun points Wait time
2 80 9
8 50 2
10 40 2
13 20 5
In this example, you could take the waves at times 8, 10 and 13 for a total of 110 fun points. If you take the wave at time 2, you can’t ride another wave until time 11, at which point only 20 fun points are left for the wave at time 13, leaving you with a total of 100 fun points. Thus, for this input, the correct answer (maximal number of fun points) is 110. Given a complete listing of waves for the day, determine the maximum number of fun points you could earn.

Input

The first line of input contains a single integer n (1 ≤ n ≤ 300,000), representing the total number of waves for the day. The ith line (1 ≤ i ≤ n) that follows will contain three space separated integers: mi, fi, and wi, (1 ≤ mi, fi, wi ≤ 10^6), representing the time, fun points, and wait time of the ith wave, respectively. You can ride another wave occurring at exactly time mi + wi after taking the ith wave. It is guaranteed that no two waves occur at the same time. The waves may not be listed in chronological order.

Output

Print, on a single line, a single integer indicating the maximum amount of fun points you can get riding waves.

Sample Input

4
8 50 2
10 40 2
2 80 9
13 20 5

Sample Output

110

Sample Input

10
2079 809484 180
8347 336421 2509
3732 560423 483
2619 958859 712
7659 699612 3960
7856 831372 3673
5333 170775 1393
2133 989250 2036
2731 875483 10
7850 669453 842

Sample Output

3330913

题目大意:

有n个浪,每个浪有开始时间,和持续时间,每个浪都有自己的兴奋值,问一个人最多可以得到多少兴奋值。

题目思路:

按浪dp做法,(看了大佬们的代码)
先给结构体按时间排序,之后开始倒退dp
状态转移方程:
1.不乘这个浪,所以等于dp[n+1]
2.找到上一个能接上自己这个浪结束的时间,然后得到l[i].h+dp[(lower_bound(l+1,l+1+n,tmp)-l)]
这就是状态转移方程

#include 
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
int n, m;
struct node{
    ll t,h,l;
    bool operator<(const node &b)const{ //sort的排序操作
        return t<b.t;    //从小到大
    }
}l[300015];
ll dp[300015];
int main(){
    while(~scanf("%d",&n)){
        memset(dp,0,sizeof dp);
        for(int i = 1;i<=n;i++){
            scanf("%I64d%I64d%I64d",&l[i].t,&l[i].h,&l[i].l);
        }
        sort(l+1,l+1+n);  //按时间排序
        for(int i = n;i>=1;i--){    //dp,从后往前推
            node tmp;
            tmp.t = l[i].t + l[i].l;  //结束时间
          dp[i]=max(dp[i+1],l[i].h+dp[(lower_bound(l+1,l+1+n,tmp)-l)]); //
        }
        printf("%I64d\n",dp[1]);
    }
    return 0;
}

按时间dp的做法:
先按时间排序,以时间来写dp,由于可以在106开始,到2* 106结束,所以结构体得开大到2*106
之后初始maxs,
判断当前一个浪时间结束时,
如果不乘这个浪,就继续取max。
如果乘这个浪,则是dp[这个浪开始的时间]+这个浪的兴奋值。
就可以写处状态状态转移方程了。
队友的ac代码:

#include  
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=3e5+5;
struct node{
	int l,f,r;
}waves[maxn];
bool cmp(node a,node b){
	if(a.r!=b.r) return a.r<b.r;
	if(a.l!=b.l) return a.l<b.l;
	return a.f<b.f; 
}
ll dp[2000008];
int main(){
	int n,i;
	cin>>n;
	int l,r,f;
	for(i=0;i<n;i++){
		cin>>waves[i].l>>waves[i].f>>r;
		waves[i].r=waves[i].l+r;
	}
	sort(waves,waves+n,cmp);
	ll maxx=0;
	int now=0;
	for(i=1;i<=2000005;i++){
		if(i==waves[now].r){
			while(i==waves[now].r){
				dp[i]=max(maxx, max(dp[i],dp[waves[now].l]+waves[now].f));
				maxx=dp[i];
				now++;
			}
		}else dp[i]=dp[i-1];
		
	}
	cout<<maxx<<endl;
    return 0;
}

Problem K — limit 4 seconds

Gears

A set of gears is installed on the plane. You are given the center coordinate and radius of each gear. For a given input and output gear, indicate what happens to the output gear if you attempt to rotate the input gear.

Input

The first line of input contains a single positive integer n (2 ≤ n ≤ 1,000), the total number of gears. Following this will be n lines, one per gear, containing three space-separated integers xi , yi , and ri (−104 ≤ xi , yi ≤ 104 , 1 ≤ ri ≤ 104 ), indicating the center coordinate and the radius of the ith gear. Assume the tooth count for each gear is sufficiently high that the gears always mesh correctly. It is guaranteed that the gears do not overlap with each other. The input gear is the
first gear in the list, and the output gear is the last gear in the list.

Output

If the input gear cannot move, print, on a single line, “The input gear cannot move.” (without the quotation marks).
If the input gear can move but is not connected to the output gear, print, on a single line, “The input gear is not connected to the output gear.” (without the quotation marks). Otherwise, print, on a single line, the ratio the output gear rotates with respect to the input gear in the form of “##:##” (without the quotation marks), in reduced form. If the output gear rotates in the opposite direction as the input gear, write the ratio as a negative ratio. For example, if the output gear rotates clockwise three times as the input gear rotates counterclockwise twice, the output should be -3:2.

Sample Input

2
0 0 100
200 0 100

Sample Output

-1:1

Sample Input

3
0 0 100
200 0 100
400 0 100

Sample Output

1:1

Sample Input

16
10 10 5
20 10 5
30 10 5
40 10 5
10 20 5
20 20 5
30 20 5
40 20 5
10 30 5
20 30 5
30 30 5
40 30 5
10 40 5
20 40 5
30 40 5
40 40 5

Sample Output

1:1

Sample Input

3
0 0 1
0 3 2
4 0 3

Sample Output

The input gear cannot move.

题目大意:

给你n个齿轮的坐标(x,y),还有半径r,问第一个齿轮能否带动最后一个齿轮转动。输出转动的速度比。

题目思路:

是否能到达直接用bfs即可,然后记录步数,奇数比为负,偶数比为正,齿轮的线速度都相同,所以直接判断半径比(用gcd)。
最关键的是怎么判断是否卡住,当时想了好久,发现奇数环就会卡住,但是太难实现了,后来才知道,直接dfs,如果有自身逆时针和顺时针相反的的,即是卡住了。
代码如下:

#include 
using namespace std;
#define reg register
typedef long long ll;

struct node{
 int x,y;
 int tx,ty;
};

int X[3005],Y[3005],Z[3005];
 int n;
 bool ff=0;
vector<node>mp;
int o=0;
void solve(int x1,int y1,int r1,int x2,int y2,int r2){
     if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)==(r1+r2)*(r1+r2)){
          node a;
          a.x=x1;
          a.y=y1;
          a.tx=x2;
          a.ty=y2;
        mp.push_back(a);
     }
}
int r[1005];
void dfs(int k)
{
	for (reg int i=0;i<n&&!ff;i++)
	if (i!=k)
	{
		if ((X[i]-X[k])*(X[i]-X[k])+(Y[i]-Y[k])*(Y[i]-Y[k])!=(Z[i]+Z[k])*(Z[i]+Z[k])) continue;
		if (!r[i])
		{
			r[i]=-r[k];
			dfs(i);
			continue;
		}
		if (r[i]*r[k]>0)
		{
			ff=1;
			return;
		}
	}
}

struct nodes{
 int h,z,step;
};

int bfs(int sx,int sy,int ex,int ey){
queue<nodes>Q;
nodes a;
a.h=sx;
a.z=sy;
a.step=0;
Q.push(a);
while(!Q.empty()){
    nodes now;
    now=Q.front();
    if(now.h==ex&&now.z==ey){
        return now.step;
    }
    for(int i=0;i<mp.size();i++){
        if(mp[i].x==now.h&&mp[i].y==now.z){
            nodes next;
            next.h=mp[i].tx;
            next.z=mp[i].ty;
            next.step=now.step+1;
            Q.push(next);
        }
    }
    Q.pop();
 }
 return -1;
}


int main(){
  cin>>n;
for(int i=0;i<n;i++){
    scanf("%d %d %d",&X[i],&Y[i],&Z[i]);
}
for(int i=0;i<n;i++){
    for(int j=i+1;j<n;j++){
        solve(X[i],Y[i],Z[i],X[j],Y[j],Z[j]);
    }
}
r[0]=1;
	dfs(0);
	if (ff)
	{
		printf("The input gear cannot move.\n");
		return 0;
	}
	if (!r[n-1])
	{
		printf("The input gear is not connected to the output gear.\n");
		return 0;
	}
  //for(int i=0;i
   // printf("%d %d %d %d\n",mp[i].x,mp[i].y,mp[i].tx,mp[i].ty);
  //}
  int h=bfs(X[0],Y[0],X[n-1],Y[n-1]);
  if(h!=-1){
    if(h%2==1)
    printf("-%d:%d\n",Z[0]/__gcd(Z[0],Z[n-1]),Z[n-1]/__gcd(Z[0],Z[n-1]));
  if(h%2==0)
    printf("%d:%d\n",Z[0]/__gcd(Z[0],Z[n-1]),Z[n-1]/__gcd(Z[0],Z[n-1]));
  }
}

略微复杂了些,这里附上其他队ac的代码:
直接用一次dfs即可完成判断是否卡住,和是否通行。nb

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1005;
struct Gear
{
	int x,y,r;
};
Gear gear[Maxn];
int n;
int r[Maxn];
bool ff;
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
void dfs(int k)
{
	for (reg int i=1;i<=n && !ff;i++)
	if (i!=k)
	{
		if ((gear[i].x-gear[k].x)*(gear[i].x-gear[k].x)+(gear[i].y-gear[k].y)*(gear[i].y-gear[k].y)!=(gear[i].r+gear[k].r)*(gear[i].r+gear[k].r)) continue;
		if (!r[i])
		{
			r[i]=-r[k];
			dfs(i);
			continue;
		}
		if (r[i]*r[k]>0)
		{
			ff=1;
			return;
		}
	}
}
int main()
{
	//freopen("K.in","r",stdin);
	//freopen("K.out","w",stdout);
	scanf("%d",&n);
	for (reg int i=1;i<=n;i++) scanf("%d%d%d",&gear[i].x,&gear[i].y,&gear[i].r);
	r[1]=1;
	dfs(1);
	if (ff)
	{
		printf("The input gear cannot move.\n");
		return 0;
	}
	if (!r[n])
	{
		printf("The input gear is not connected to the output gear.\n");
		return 0;
	}
	int temp=gcd(gear[1].r,gear[n].r);
	if(gear[n].r<gear[1].r)
		swap(gear[n].r,gear[1].r);
	if (r[1]==r[n])
	{
		printf("%d:%d\n",gear[n].r/temp,gear[1].r/temp);
		return 0;
	}
	printf("%d:%d\n",-gear[n].r/temp,gear[1].r/temp);
	return 0;
}

你可能感兴趣的:(训练赛)