Codeforces Round #488 by NEAR (Div. 2)(01分数规划)

E. Careful Maneuvering
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There are two small spaceship, surrounded by two groups of enemy larger spaceships. The space is a two-dimensional plane, and one group of the enemy spaceships is positioned in such a way that they all have integer yy-coordinates, and their xx-coordinate is equal to 100−100, while the second group is positioned in such a way that they all have integer yy-coordinates, and their xx-coordinate is equal to 100100.

Each spaceship in both groups will simultaneously shoot two laser shots (infinite ray that destroys any spaceship it touches), one towards each of the small spaceships, all at the same time. The small spaceships will be able to avoid all the laser shots, and now want to position themselves at some locations with x=0x=0 (with not necessarily integer yy-coordinates), such that the rays shot at them would destroy as many of the enemy spaceships as possible. Find the largest numbers of spaceships that can be destroyed this way, assuming that the enemy spaceships can't avoid laser shots.

Input

The first line contains two integers nn and mm (1n,m601≤n,m≤60), the number of enemy spaceships with x=100x=−100 and the number of enemy spaceships with x=100x=100, respectively.

The second line contains nn integers y1,1,y1,2,,y1,ny1,1,y1,2,…,y1,n (|y1,i|10000|y1,i|≤10000) — the yy-coordinates of the spaceships in the first group.

The third line contains mm integers y2,1,y2,2,,y2,my2,1,y2,2,…,y2,m (|y2,i|10000|y2,i|≤10000) — the yy-coordinates of the spaceships in the second group.

The yy coordinates are not guaranteed to be unique, even within a group.

Output

Print a single integer – the largest number of enemy spaceships that can be destroyed.

Examples
input
Copy
3 9
1 2 3
1 2 3 7 8 9 11 12 13
output
Copy
9
input
Copy
5 5
1 2 3 4 5
1 2 3 4 5
output
Copy
10
Note

In the first example the first spaceship can be positioned at (0,2)(0,2), and the second – at (0,7)(0,7). This way all the enemy spaceships in the first group and 66 out of 99 spaceships in the second group will be destroyed.

In the second example the first spaceship can be positioned at (0,3)(0,3)

, and the second can be positioned anywhere, it will be sufficient to destroy all the enemy spaceships


题目大意就是在坐标平面上关于x=0对称的地方有若干飞船 会对着某两个位于x=0 y任意的点发射两束激光 然后杀死对面的一些飞船 问把那两个点放哪里是杀死的飞船最多

仔细看看好像确实不难 就是题目那个-100和100是没有用的 他们y坐标的一半就是点可能放置的地方(如果你放别的地方的话根本杀不死飞船) 也就是说你要在所有飞船在x=0这条轴上的所有投影点选两个使得杀死的最多 那么用T1[A+B][i]来表示在A+B这个截距上 左边第i个飞船会死 T1[A+B][J] 表示右边第j个会死 要注意的是死的飞船是有可能重复的 所以我们要取其交集 交集的话要么用STL里面的集合或者用bitset里面的或运算:

.

#include <set>
#include <map>
#include <list>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int maxn=50005;
bitset<65> tt1[maxn],tt2[maxn];
int a[70],b[70];
vector<int>test;
map<int,bool>has;

int main()
{
    ios::sync_with_stdio(false);
    bitset<65> *t1=tt1+25000,*t2=tt2+25000;
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int j=1;j<=m;j++)
    {
        cin>>b[j];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            t1[a[i]+b[j]][i]=1;
            t2[a[i]+b[j]][j]=1;
            if(!has[a[i]+b[j]])
            {
                has[a[i]+b[j]]=1;
                test.push_back(a[i]+b[j]);
            }
        }
    }
    int ans=0,tmp;
    for(int i=test.size()-1;i>=0;i--)
    {
        for(int j=test.size()-1;j>=0;j--)
        {
            tmp=(t1[test[i]]|t1[test[j]]).count()+(t2[test[i]]|t2[test[j]]).count();
            ans=max(ans,tmp);
        }
    }
    cout<<ans<<endl;
}


F题:

F. Compute Power
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You need to execute several tasks, each associated with number of processors it needs, and the compute power it will consume.

You have sufficient number of analog computers, each with enough processors for any task. Each computer can execute up to one task at a time, and no more than two tasks total. The first task can be any, the second task on each computer must use strictly less power than the first. You will assign between 1 and 2 tasks to each computer. You will then first execute the first task on each computer, wait for all of them to complete, and then execute the second task on each computer that has two tasks assigned.

If the average compute power per utilized processor (the sum of all consumed powers for all tasks presently running divided by the number of utilized processors) across all computers exceeds some unknown threshold during the execution of the first tasks, the entire system will blow up. There is no restriction on the second tasks execution. Find the lowest threshold for which it is possible.

Due to the specifics of the task, you need to print the answer multiplied by 1000 and rounded up.

Input

The first line contains a single integer n (1 ≤ n ≤ 50) — the number of tasks.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 108), where ai represents the amount of power required for the i-th task.

The third line contains n integers b1, b2, ..., bn (1 ≤ bi ≤ 100), where bi is the number of processors that i-th task will utilize.

Output

Print a single integer value — the lowest threshold for which it is possible to assign all tasks in such a way that the system will not blow up after the first round of computation, multiplied by 1000 and rounded up.

Examples
input
Copy
6
8 10 9 9 8 10
1 1 1 1 1 1
output
Copy
9000
input
Copy
6
8 10 9 9 8 10
1 10 5 5 1 10
output
Copy
1160
Note

In the first example the best strategy is to run each task on a separate computer, getting average compute per processor during the first round equal to 9.

In the second task it is best to run tasks with compute 10 and 9 on one computer, tasks with compute 10 and 8 on another, and tasks with compute 9 and 8 on the last, averaging (10 + 10 + 9) / (10 + 10 + 5) = 1.16 compute power per processor during the first round.



这题看得很懵 网上查了才知道这类题叫做01分数规划问题 01分数规划就是给一个数列Ai 和一个数列Bi 然后求∑Ai/∑Bi 的最值  比较通用的方法是二分一个答案ans 然后问题就变成 ∑Ai/∑Bi≤ans 即∑(Ai-Bi*ans)≤0 这里有一个限制条件就是我们放置的第二台机器的A必须要小于第一台 那么我们可以先按照A从大到小排序  再用动态规划建立方程

设f(i,j,k)表示对于第i台机器  他有j台机器的功率大于他且这j台机器都没有第二台机器  有k台机器功率等于他且这k台机器都没有第二台机器 所得的一个最小值 最终答案显然就是f(0,0,0)

那么对于每台机器他有两个选择 要么成为第一台机器 要么成为第二台 这里分下情况:

1: Ai=Ai+1

如果选择成为第一台的话就意味对于i而言j不变 而k要+1 如果选择成为第二台的话就意味着对于第i+1台机器来说他的j-1 而k不变 可得方程:
f(i,j,k)=min{f(i+1,j-1,k),f(i+1,j,k+1)+a【i】-ans*b【i】
}

同理对于 Ai≠Ai+1 有:

f(i,j,k)=min{f(i+1,k+j-1,0),f(i+1,j+k+1,0)+a【i】-ans*b【i】}

#include <set>
#include <map>
#include <list>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

typedef long long ll;
const int inf=0x7fffffff;
const int N=55;
double X,f[N][N][N];
bool vis[N][N][N];
int n;
ll ans;

struct node
{
    double a,c;
};
node t[N];

bool cmp(node x,node y)
{
    return x.a>y.a;
}
double dfs(int i,int j,int k)
{
    if(i>=n) return 0;
    if(vis[i][j][k]) return f[i][j][k];
    vis[i][j][k]=1;
    double mn=inf;
    if(i<n-1&&t[i].a==t[i+1].a)
    {
        if(j) mn=min(mn,dfs(i+1,j-1,k));
        mn=min(mn,dfs(i+1,j,k+1)+t[i].a-X*t[i].c);
    }
    else if(t[i].a!=t[i+1].a||i==n-1)
    {
        if(j) mn=min(mn,dfs(i+1,j+k-1,0));
        mn=min(mn,dfs(i+1,j+k+1,0)+t[i].a-X*t[i].c);
    }
    return f[i][j][k]=mn;
}
bool judge(double k)
{
    X=k;
    memset(vis,0,sizeof(vis));
    memset(f,0,sizeof(f));
    return dfs(0,0,0)<=0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>t[i].a;
    }
    for(int i=0;i<n;i++)
    {
        cin>>t[i].c;
    }
    sort(t,t+n,cmp);
    double l=0.0,r=1e8;
    for(int T=1;T<100;T++)
    {
        double mid=(r+l)/2.0;
        if(judge(mid)) r=mid;
        else l=mid;
    }
    ans=(ceil)(l*1000);
    cout<<ans<<endl;
}
01分数规划可以用来解决很多问题  比如最优比例的生成树 详细见: 点击打开链接

猜你喜欢

转载自blog.csdn.net/weixin_39302444/article/details/80926519
今日推荐