2020hdu多校第四场比赛及补题

1005 Equal Sentences

队友过的一题

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 1e5 + 7;
const int MOD = 1e9 + 7;

int T;
int n;
string str;
string tmp, word;
int cnt;
int dp[MAXN][2];
int vis[MAXN];
int ans;

int32_t main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> T;
    while (T--)
    {
        memset(vis, 0, sizeof(vis));
        cnt = 0;
        ans = 0;
        word = "";
        cin >> n;
        for (int i = 1; i <= n; ++i)
        {
            cin >> str;
            if (str != word)
            {
                cnt++;
                word = str;
            }
            vis[i] = cnt;
        }
        dp[0][0] = dp[0][1] = 0;
        dp[1][0] = 1;
        dp[1][1] = 0;
        for (int i = 2; i <= n; ++i)
        {
            if (vis[i] != vis[i - 1])
            {
                dp[i][0] = dp[i - 1][0] + dp[i - 1][1] % MOD;
                dp[i][1] = dp[i - 1][0] % MOD;
            }
            else
            {
                dp[i][0] = dp[i - 1][0] + dp[i - 1][1] % MOD;
                dp[i][1] = 0 % MOD;
            }
        }
        ans = dp[n][0] + dp[n][1];
        ans %= MOD;
        cout << ans << endl;
    }
    return 0;
}

  

1002 Blow up the Enemy

队友过的一题

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int data[1002];
int main(void){
    int t;
    cin >> t;
    int n;
    while(t--){
        scanf("%d", &n);
        int ai,di;
        int minn=999999999;
        for(int i=1;i<=n;i++){
            scanf("%d %d", &ai, &di);
            if((100%ai)==0){
                data[i]= di*(100/ai-1);
            }else{
                data[i] = di*(100/ai);
            }
            if(minn > data[i]){
                minn = data[i];
            }
        }
        int ans = 0;
        for(int i=1;i<=n;i++){
            if(minn < data[i]){
                ans += 10;
            }else if(minn == data[i]){
                ans += 5;
            }else{
                ans += 0;
            }
        }
        double res = (double)ans/(double)n/10.0;
        cout << res << endl;
    }
    return 0;
}

  

1011 Kindergarten Physics

???题,我们队三人还真一直在算,直到我偷听到答案。。。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const double res = 1e-10;
int main()
{
	int T,a,b,d;
	double t;
	cin>>T;
	while(T--){
		cin>>a>>b>>t>>d;
		t-=res;
		printf("%.10lf\n",t);
	}
	return 0;
} 

 

1004 Deliver the Cake

n个点,m条边求最短路,

点有3个状态,L,R,M

L点到R点或R点到L点要额外增加 x 的距离,M点可当成L点或当成R点,M点不能同时当成L点和R点

看起来挺简单的,但比赛时没做出来,一直T

我乱魔改dijkstra,用了自己不会的语法

还是拆点好,直接把M点拆成一个L点和一个R点,然后建图,拆点建图细节比较多,我改了挺久

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<vector>

using namespace std;
const int MAXN = 2e5+7;
const long long INF = 1e18+7;

template<class T>inline void read(T& res)
{
    char c; T flag = 1;
    while ((c = getchar()) < '0' || c > '9')if (c == '-')flag = -1; res = c - '0';
    while ((c = getchar()) >= '0' && c <= '9')res = res * 10 + c - '0'; res *= flag;
}

struct EDGE{
	int to,next;
	long long d;
}edge[MAXN*8];
int head[MAXN],tot;

long long n,m,s,t,x; 
char shou[MAXN];
long long dis[MAXN];

void add(int u,int v,long long w){
	++tot;
	edge[tot].to = v;
	edge[tot].d = w;
	edge[tot].next = head[u];
	head[u] = tot;
}

void dijkstra(int st) {
	priority_queue< pair<long long,int> , vector<pair<long long,int> >, greater<pair<long long,int> > >que;
	dis[st] = 0;
	que.push({0,st});
	while(!que.empty()){
		int node = que.top().second;
		long long dt = que.top().first;
		if(dis[node] < dt){
			que.pop();
			continue;
		}
		que.pop();
		for(int i = head[node];i;i = edge[i].next ){
			int po = edge[i].to;
			long long lo = edge[i].d;
			if(dis[po] > dis[node] + lo){
				dis[po] = dis[node] + lo;
				que.push({dis[po],po});
			}
		}
	}
    return;
}

int main()
{
	//freopen("D.in","r",stdin); 
	int T;
	int u,v;
	long long d;
	cin>>T;
	while(T--){
		tot = 0;
		scanf("%lld%lld%lld%lld%lld",&n,&m,&s,&t,&x);
		scanf("%s",shou + 1);
		for(int i = 1;i <= n; i++){
			head[i] = head[i+n] = 0;
			dis[i] = dis[i+n] = INF;
		}
		for(int i = 1;i <= m; i++ ){
			read(u);read(v);read(d);
			if(shou[u] == 'R') u += n;
			if(shou[v] == 'R' ) v += n;
			if(u <= n && v <= n) {
				add(u,v,d);
				add(v,u,d);
			}
			else if(u>n&&v>n){
				add(u,v,d);
				add(v,u,d);
			}
			else {
				add(u,v,d+x);
				add(v,u,d+x);
			}
			if(u<=n&&v<=n&&shou[u]=='M'&&shou[v]=='M'){ 
				add(u,v+n,d+x);
				add(v+n,u,d+x);
				add(u+n,v,d+x);
				add(v,u+n,d+x);
				add(u+n,v+n,d);
				add(v+n,u+n,d);
			}
			else if (u<=n&&shou[u] == 'M'){
				if(v<=n){
					add(u+n,v,d+x);
					add(v,u+n,d+x);	
				}
				else{
					add(u+n,v,d);
					add(v,u+n,d);
				}
			}
			else if(v<=n&&shou[v] == 'M'){
				if(u<=n){
					add(u,v+n,d+x);
					add(v+n,u,d+x);
				}
				else{
					add(u,v+n,d);
					add(v+n,u,d);
				}
			}
		}
		long long ans;
		if(shou[s]=='L'){
			dijkstra(s);
			ans = min(dis[t],dis[t+n]);
		}
		else if(shou[s]=='R'){
			dijkstra(s+n);
			ans = min(dis[t],dis[t+n]);
		}
		else{
			dijkstra(s);
			ans = min(dis[t],dis[t+n]);
			for(int i = 1;i<=n;i++){
				dis[i] = dis[i+n] = INF;
			}
			dijkstra(s+n);
			ans = min(ans,min(dis[t],dis[t+n]));
		}
		printf("%lld\n",ans);
	}	
	return 0;
}

  

1007 Go Running

补题

看了下队友的代码,队友的代码比较神奇,有我没见过的语法,变量名又是fuck,又是shit的。。。

其实是挺简单的一题,我一看,就想到这是一个二分图题,可惜我比赛时没看这题(一直在搞1004qAq)

题目意思可以转化为给n组 t 和 x,每组t,x表示 t-x或t+x的位置上有人,问最少有多少人

把每个t-x点放到左边,每个t+x点放到右边,每组的t-x点连向对应的t+x点,发现就是个二分图最小点覆盖问题,最小点覆盖就是二分图最大匹配(我当时忘记了二分图最小点覆盖是什么,但直觉上感觉这就是个二分图最大匹配)

虽然一下就想到二分图,但我还是补了挺久

我想用网络流来做二分图最大匹配,而这题数据比较大,要用dinic,而我只会EK,不会dinic,我dinic用的是软白的板子,用不来,在那套板子套了挺久还是没套好,然后又去检查建图,最后只好用我好久没用的二分图最大匹配模板,重新写一遍,过了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<map>
#include<queue>
using namespace std;
const int MAXN = 1e5+7;
vector<int> graph[MAXN];
int n;
int pei[MAXN],cc[MAXN];
bool eft(int st, int cur){
	if(cc[st]==cur) return false;
	cc[st] = cur;
	for(int i = 0;i<graph[st].size();i++){
		int po = graph[st][i];
		if(pei[po] == st) continue;
		if(pei[po] == -1||eft(pei[po],cur)){
			pei[po] = st;
			return true;
		}
	}
	return false;
}
int main()
{
	//freopen("G.in","r",stdin);
	int T;
	cin>>T;
	int t,x;
	while(T--){
		cin >> n;
		map<long long,int>ant1,ant2;
		int cnt1 = 0,cnt2 = 0;
		for(int i = 1;i <= n;i++){
			scanf("%d%d",&t,&x);
			if(!ant1[x-t]) ant1[x-t] = ++cnt1;			
			if(!ant2[x+t]) ant2[x+t] = ++cnt2;
			graph[ant1[x-t]].push_back(ant2[x+t]);
		}	
		for(int i = 1;i <= cnt2;i++) pei[i] = -1;
		for(int i = 1;i <= cnt1;i++) cc[i] = -1;
		int ans = 0;	
		for(int i = 1;i <= cnt1;i++) if(eft(i,i)) ans++;
		cout<<ans<<endl;
		for(int i = 1;i <= cnt1;i++) graph[i].clear();
	}
	return 0;
} 

  

原文地址:https://www.cnblogs.com/ruanbaitql/p/13557485.html