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;
}

浙公网安备 33010602011771号