题意:给你h个人类星球和a个外星星球,每个人类星球开始有x艘飞船,另外每年可以生产y艘,每个外星星球也是这样。现在人类派某个星球的飞船去攻打外星星球,如果飞船到达外星星球时,人类飞船数量大于等于外星飞船数量,则人类获胜,每个人类星球只能攻打一个外星星球,现在要你求出最少的时间,使得人类可以完全消灭所有的外星星球。
分析:直接二分最长时间即可。
代码:
//复杂度:O(n*e)
#pragma comment(linker,"/STACK:102400000,102400000")
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
typedef long long ll; //记得必要的时候改成无符号
const int maxn=300; //点数
const int maxm=1000005; //边数
struct EdgeNode
{
int to;
int next;
}edge[maxm];
int head[maxn],cnt;
void add(int x,int y)
{
edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt++;
}
int n,m,v[maxn],pre[maxn];
void init()
{
cnt=1;
memset(head,-1,sizeof(head));
}
bool dfs(int x)
{
int y;
for(int i=head[x];i!=-1;i=edge[i].next)
{
y=edge[i].to;
if(!v[y])
{
v[y]=1;
if(!pre[y]||dfs(pre[y]))
{
pre[y]=x;
return true;
}
}
}
return false;
}
int erfenpipei()
{
int sum=0;
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++)
{
memset(v,0,sizeof(v));
if(dfs(i))
sum++;
}
return sum;
}
int h,a,w[maxn][maxn];
struct p
{
int x,y;
}pa[maxn],al[maxn];
int pd(int h,int h1,int a,int a1,int t1,int x)
{
double q;
if(h1-a1>0){
q=(double)(a+h1*t1-h)/(h1-a1);
if(x>=q)return 1;
else return 0;
}
else{
if(h-a-h1*t1>=0)return 1;
else return 0;
}
}
void build(int o)
{
int i,j;
init();
for(i=1;i<=h;i++){
for(j=1;j<=a;j++){
if(pd(pa[i].x,pa[i].y,al[j].x,al[j].y,w[i][j],o))
add(i,j);
}
}
}
int main()
{
int i,j;
int l,mid,r,sc;
while(~scanf("%d%d",&h,&a)&&(h+a))
{
sc=-1; n=h;
for(i=1;i<=n;i++)scanf("%d%d",&pa[i].x,&pa[i].y);
for(i=1;i<=a;i++)scanf("%d%d",&al[i].x,&al[i].y);
for(i=1;i<=h;i++)
for(j=1;j<=a;j++)
scanf("%d",&w[i][j]);
l=0; r=1000000005;
while(l<=r){
mid=(l+r)/2;
build(mid);
if(erfenpipei()==a){
sc=mid;
r=mid-1;
}
else l=mid+1;
}
if(sc==-1)printf("IMPOSSIBLE\n");
else printf("%d\n",sc);
}
return 0;
}