World final 2017 题解
链接:https://pan.baidu.com/s/1kVQc9d9
Problem A:
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 222;
struct Point
{
long long x, y;
Point(long long x = 0, long long y = 0) : x(x), y(y) { }
void read()
{
scanf("%lld %lld", &x, &y);
}
};
typedef Point Vector;
Vector operator - (const Point &A, const Point &B)
{
return Vector(A.x - B.x, A.y - B.y);
}
long long Cross(const Vector &A, const Vector &B)
{
return A.x * B.y - A.y * B.x;
}
long long Dot(const Vector &A, const Vector &B)
{
return A.x * B.x + A.y * B.y;
}
double inter(Point p, Vector v, Point q, Vector w)
{
Vector u = p - q;
return 1.0 * Cross(w, u) / Cross(v, w);
}
bool on(Point p, Point a, Point b)
{
return Cross(p - a, p - b) == 0;
}
int dcmp(long long x)
{
if (x == 0)
return 0;
return x > 0 ? 1 : -1;
}
int n;
Point p[maxn];
double ans = 0.0;
void solve(Point A, Point B)
{
vector<double> lst;
for (int i = 0; i < n; ++i)
{
if (dcmp(Cross(p[i] - A, B - A)) * dcmp(Cross(p[i + 1] - A, B - A)) >= 0)
continue;
lst.push_back(inter(A, B - A, p[i], p[i + 1] - p[i]));
}
for (int i = 0; i < n; ++i)
{
if (!on(p[i], A, B))
continue;
Point L = p[(i + n - 1) % n];
Point N = p[(i + 1) % n];
Point P = p[i];
long long dir = Cross(B - A, L - A);
double pos = 1.0 * Dot(P - A, B - A) / Dot(B - A, B - A);
if (dir == 0)
{
if (Dot(B - A, P - L) > 0)
{
if (Cross(B - A, N - A) > 0)
lst.push_back(pos);
}
else
{
if (Cross(B - A, N - A) < 0)
lst.push_back(pos);
}
}
else if (dir > 0)
{
if (Cross(B - A, N - A) < 0)
lst.push_back(pos);
else if (Cross(B - A, N - A) == 0 && Dot(B - A, N - P) > 0)
lst.push_back(pos);
}
else
{
if (Cross(B - A, N - A) > 0)
lst.push_back(pos);
else if (Cross(B - A, N - A) == 0 && Dot(B - A, N - P) < 0)
lst.push_back(pos);
}
}
sort(lst.begin(), lst.end());
double len = sqrt(Dot(B - A, B - A));
for (int i = 0; i < (int)lst.size(); i += 2)
ans = max(ans, (lst[i + 1] - lst[i]) * len);
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; ++i)
p[i].read();
p[n] = p[0];
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
solve(p[i], p[j]);
printf("%.10f\n", ans);
return 0;
}
Problem C:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 305, M = 100005;
const ll inf = 1ll << 60;
int head[N];
struct Edge {
int nxt, to, cow;
ll cost;
Edge() {}
Edge(int nxt, int to, int cow, ll cost) : nxt(nxt), to(to), cow(cow), cost(cost) {}
} ed[M];
int ecnt, mx_flow;
ll mi_cost;
void init() {
mx_flow = mi_cost = ecnt = 0;
memset(head, -1, sizeof(head));
}
void addE(int u, int v, int cow, ll cost) {
ed[ecnt] = Edge(head[u], v, cow, cost);
head[u] = ecnt ++;
ed[ecnt] = Edge(head[v], u, 0, -cost);
head[v] = ecnt ++;
}
queue <int> Q;
ll dis[N];
int pre[N], inq[N], tot;
bool spfa(int S, int T) {
for (int i = 0; i < tot; ++ i)
dis[i] = inf;
dis[S] = 0;
Q.push(S);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
for (int e = head[u]; ~e; e = ed[e].nxt) {
if (!ed[e].cow)
continue;
int v = ed[e].to;
if (dis[v] > dis[u] + ed[e].cost) {
dis[v] = dis[u] + ed[e].cost;
pre[v] = e;
if (!inq[v]) {
inq[v] = 1;
Q.push(v);
}
}
}
}
return dis[T] < 0;
}
void aug(int S, int T) {
int flow = 1 << 30;
for (int u = T; u != S; u = ed[pre[u] ^ 1].to)
flow = min(flow, ed[pre[u]].cow);
for (int u = T; u != S; u = ed[pre[u] ^ 1].to) {
ed[pre[u]].cow -= flow;
ed[pre[u] ^ 1].cow += flow;
mi_cost += flow * ed[pre[u]].cost;
}
mx_flow += flow;
}
int A[105][105];
int mxr[105], mxc[105];
int idr[105], idc[105];
int main() {
init();
int n, m;
scanf("%d%d", &n, &m);
long long sum = 0;
for (int i = 0; i < n; ++ i)
for (int j = 0; j < m; ++ j)
scanf("%d", A[i] + j), sum += A[i][j];
for (int i = 0; i < n; ++ i) {
mxr[i] = - (1 << 30);
for (int j = 0; j < m; ++ j)
mxr[i] = max(mxr[i], A[i][j]);
}
for (int j = 0; j < m; ++ j) {
mxc[j] = - (1 << 30);
for (int i = 0; i < n; ++ i)
mxc[j] = max(mxc[j], A[i][j]);
}
tot = 0;
for (int i = 0; i <= n; ++ i)
idr[i] = tot ++;
for (int i = 0; i <= m; ++ i)
idc[i] = tot ++;
int src = tot ++, des = tot ++;
int use = 0;
for (int i = 0; i < n; ++ i)
if (mxr[i])
addE(src, idr[i], 1, - (1 << 30)), ++ use;
for (int i = 0; i < m; ++ i)
if (mxc[i])
addE(idc[i], des, 1, - (1 << 30)), ++ use;
addE(src, idr[n], 1 << 30, 0);
addE(idc[m], des, 1 << 30, 0);
long long ans = 0;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
if (A[i][j] == 0)
continue;
++ ans;
if (mxr[i] < mxc[j]) {
addE(idr[i], idc[m], 1, mxr[i] - 1);
} else if(mxr[i] > mxc[j]) {
addE(idr[n], idc[j], 1, mxc[j] - 1);
} else {
addE(idr[i], idc[j], 1, mxr[i] - 1);
addE(idr[i], idc[m], 1, mxr[i] - 1);
addE(idr[n], idc[j], 1, mxr[i] - 1);
}
}
}
while(spfa(src, des))
aug(src, des);
mi_cost += (1ll << 30) * use;
ans += mi_cost;
cout << sum - ans << endl;
return 0;
}
Problem E:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int n;
double t,d[maxn],s[maxn];
double check(double x){
double res = 0;
for(int i=0;i<n;i++){
if(s[i]+x<=0){
return 10000000.0;
}
res += d[i]/(s[i]+x);
}
return res;
}
int main(){
cin>>n>>t;
for(int i=0;i<n;i++)
cin>>d[i]>>s[i];
double l=-1e9,r=1e9;
for(int cas=0;cas<=100;cas++){
double mid = (l+r)/2.0;
if(check(mid)>t)l=mid;
else r=mid;
}
printf("%.12f\n",l);
}
Problem F:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 260;
long long d[maxn];
long long dp[maxn][maxn];
long long cal[maxn][maxn];
int n,m;
int a,b;
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
a++;
d[a]+=b;
}
for(int i=0;i<maxn;i++){
for(int j=2;j<maxn;j++){
dp[i][j]=10000000000000000LL;
}
}
for(int i=1;i<=256;i++){
for(int j=i+1;j<=256;j++){
for(int i2=i+1;i2<j;i2++){
cal[i][j]+=1ll*min(i2-i,j-i2)*min(i2-i,j-i2)*d[i2];
}
}
}
for(int i=1;i<=256;i++){
for(int j=1;j<i;j++){
dp[i][1]+=1ll*(i-j)*(i-j)*d[j];
}
}
for(int i=1;i<=256;i++){
for(int j=1;j<=i;j++){
for(int i2=2;i2<=m;i2++){
dp[i][i2]=min(dp[i][i2],dp[j][i2-1]+cal[j][i]);
}
}
}
for(int i=1;i<=256;i++){
for(int j=i+1;j<=256;j++){
dp[i][m]+=1ll*(j-i)*(j-i)*d[j];
}
}
long long Res = 10000000000000000LL;
for(int i=1;i<=256;i++){
Res = min(Res,dp[i][m]);
}
cout<<Res<<endl;
}
Problem I:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 30;
int mp[maxn][maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
string a,b;
for(int i=0;i<n;i++){
cin>>a>>b;
mp[a[0]-'a'][b[0]-'a']=1;
}
for(int k=0;k<26;k++){
mp[k][k]=1;
for(int i=0;i<26;i++){
for(int j=0;j<26;j++){
if(mp[i][k]&&mp[k][j])
mp[i][j]=1;
}
}
}
string s1,s2;
for(int i=1;i<=m;i++){
cin>>s1>>s2;
if(s1.size()!=s2.size()){
cout<<"no"<<endl;
continue;
}
int flag = 1;
for(int j=0;j<s1.size();j++){
if(mp[s1[j]-'a'][s2[j]-'a']==0)
flag = 0;
}
if(flag == 0)
cout<<"no"<<endl;
else
cout<<"yes"<<endl;
}
}