xjoi奋斗群群赛13

群赛地址;

https://vjudge.net/contest/186396#problem

A - Dima and Guards

  CodeForces - 366A 

题意:这是一道水题.

题解:

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	int n,a,b,c,d;
	int p=-1,x,y;
	cin>>n;
	for(int i=1;i<=4;i++){
		cin>>a>>b>>c>>d;
		if(min(a,b)+min(c,d)<=n){
		p=i;
		x=min(a,b);y=n-x;
		}
	}
	if(p==-1)cout<<-1;
	else cout<<p<<' '<<x<<' '<<y;
}

B - Dima and To-do List

  CodeForces - 366B 

题意:一个序列,每隔k个数取一个数,求最小和的首先取位置.

题解:

#include<bits/stdc++.h>
using namespace std;
int n,k,a[100010],sum[100010];
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%d",a+i);
	}
	for(int i=1;i<=k;i++){
		for(int j=i;j<=n;j+=k){
			sum[i]+=a[j];
		}
	}
	int minn=sum[1],p=1;
	for(int i=2;i<=k;i++){
		if(minn>sum[i]){
			minn=sum[i];
			p=i;
		}
	}
	printf("%d",p);
}


C - Dima and Salad

  CodeForces - 366C 

题意:给出一个序列,求和为0的序列使一个参数最大.

思路:背包

题解:

#include<bits/stdc++.h>
using namespace std;
const int add=1e4;
int n,k,a[110],b[110],w[110],dp[110][110010],sum[110][110010];
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) w[i]=b[i]*k-a[i];
	for(int i=1;i<=n;i++){
		dp[i][w[i]+add]=1;
		sum[i][w[i]+add]=max(sum[i][w[i]+add],a[i]);
		for(int j=0;j<=110000;j++){
			if(dp[i-1][j]){
				dp[i][j]=1;
				sum[i][j]=max(sum[i][j],sum[i-1][j]);
				dp[i][j+w[i]]=1;
				sum[i][j+w[i]]=max(sum[i][j+w[i]],sum[i-1][j]+a[i]);
			}
		}
	}
	if(dp[n][add])printf("%d\n",sum[n][add]);
	else printf("-1\n");
}

D - Dima and Trap Graph

  CodeForces - 366D 

题意:一个人要在一个图中从1走到n,图中每个边有一个l值,r值,那个人的数在l,r之间才能通过.问那个人能取的数的种类数.

失败的代码:

#include<iostream>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;

const int MAXN=1000;
const int INF=0x3f3f3f3f;

struct Edge {
	int from, to;
	bitset < 1001 > cap;
	bitset < 1001 > flow;
	Edge(int u,int v,int c,int f) : from(u), to(v) {
		this->cap.reset();
		this->flow.reset();
		for(int i=c;i<=f;i++) {
			this->cap.set(i);
		}
	}
};

struct EdmondsKarp {
	int n, m, l;
	vector < Edge > edges;
	vector < int > G[MAXN];
	bitset < 1001 > a[MAXN];
	int p[MAXN];

	void init() {
		for(int i = 0; i < n; ++i) {
			G[i].clear();
		}
		edges.clear();
	}

	void AddEdge(int from, int to, int lef, int rig) {
		edges.push_back(Edge(from, to, lef, rig));
		edges.push_back(Edge(to, from, lef, rig)); //反向弧
		l = edges.size();
		G[from].push_back(l - 2);
		G[to].push_back(l - 1);
	}

	int Maxflow(int s, int t) {
		cout<<"BEGIN:\n";
		bitset < 1001 > flow;
		for(;;) {
			cout<<"new queue:\n";
			system("pause");
			queue < int > Q;
			Q.push(s);
			for(int i=1;i<=n;i++) {
				a[i].reset();
			}
			a[s].set();//初始源点有无限个物品

			while(!Q.empty()) {
				int x = Q.front();
				Q.pop();
				cout<<"	new repeat:x = "<<x<<endl;

				for(int i = 0; i < G[x].size(); ++i) {
					cout<<"(1)";
					Edge &e = edges[G[x][i]];
					cout<<"		new point: point = "<<e.to<<endl;

					if(a[e.to].none() && ((e.flow & a[x]) != a[x]) ) { // 查找任意边流动物品
						cout<<"(2)";
						p[e.to] = G[x][i];
//						a[e.to] = min(a[x], e.cap - e.flow);
						a[e.to] = (a[x] | a[e.to]) & e.cap;
						cout<<"			new bit: bit = "<<a[e.to].count()<<endl;
						if(a[e.to].any()) {
							Q.push(e.to);
							cout<"(3)";
						}
					}
				}
				cout<<"(4)";
				if(a[t].any()) { //如果有增广路,退出
				cout<<"(5)";
					break;
				}
			}

			if(a[t].none()) { //没有增广路,现在的结果即为最大流
				cout<<"(6)";
				break;
			}

			for(int u = t; u != s; u = edges[p[u]].from) { // 反向修改流量
				cout<<"(7)";
				edges[p[u]].flow |= a[t];
				cout<<"edges_flow: "<<p[u]<<" "<<edges[p[u]].flow.count()<<endl;
				edges[p[u] ^ 1].flow ^= a[t];
			}

			flow |= a[t];//增加总流量
//			cout<<"flow = "<<flow.count()<<" a[t] = "<<a[t]<<endl;
		}

		return flow.count();
	}
};


int main() {
	EdmondsKarp ED;
	scanf("%d%d",&ED.n,&ED.m);
	int a,b,c,d;
	for(int i=1;i<=ED.m;i++) {
		scanf("%d%d%d%d",&a,&b,&c,&d);
		ED.AddEdge(a,b,c,d);
		
	}
	cout<<"================================================="<<ED.Maxflow(1,ED.n);
}

tijie

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
const int INF = 0x3f3f3f3f;
struct node
{
    int v, l, r;
    node(int vv, int ll, int rr): v(vv), l(ll), r(rr) {}
};
int n, m, ans, recl[maxn], recr[maxn];
bool vis[maxn], book[maxn];
vector<node> g[maxn];

void dfs(int u, int l, int r)
{
    if(u == n)
    {
        ans = max(ans, r-l+1);
        return ;
    }
    for(int i = 0; i < g[u].size(); i++)
    {
        int v = g[u][i].v;
        int L = g[u][i].l;
        int R = g[u][i].r;
        if(!vis[v])
        {
            int tl = max(L, l);
            int tr = min(R, r);
            if(tl <= tr)
            {
                if(ans != -1 && tr-tl+1 <= ans) continue;//
                if(book[v] && tl >= recl[v] && tr <= recr[v]) continue ;//
                book[v] = 1;
                recl[v] = tl, recr[v] = tr;
                vis[v] = 1;
                dfs(v, tl, tr);
                vis[v] = 0;
            }
        }
    }
}

int main(void)
{
    while(cin >> n >> m)
    {
        memset(vis, 0, sizeof(vis));
        memset(book, 0, sizeof(book));
        for(int i = 1; i <= n; i++)
            g[i].clear();
        for(int i = 1; i <= m; i++)
        {
            int u, v, l, r;
            scanf("%d%d%d%d", &u, &v, &l, &r);
            g[u].push_back(node(v, l, r));
            g[v].push_back(node(u, l, r));
        }
        ans = -1;
        dfs(1, -INF, INF);
        if(ans == -1) puts("Nice work, Dima!");
        else printf("%d\n", ans);
    }
    return 0;
}

E - Dima and Magic Guitar

  CodeForces - 366E 


题意:一个人弹吉他,有一些弦和片,移动到另一个弦和片的距离为曼哈顿距离.给出他要弹的曲子和吉他上各种弦和片的生成音符,求他最大的单次移动距离.

思路:由于只要求单次距离,所以预处理n*m一边就行了.

题解:

#include<iostream>  
#include<cstdio>  
#include<cstring>  
using namespace std;  
int n,m,k,s;  
int f[10][2],b[10][2]; 
int main(){  
    memset(f,192,sizeof(f));  
    memset(b,63,sizeof(b));  
    scanf("%d%d%d%d",&n,&m,&k,&s);  
    for(int i=1;i<=n;i++){  
        for(int j=1;j<=m;j++){  
            int a;  
            scanf("%d",&a);  
            f[a][0]=max(f[a][0],i+j); f[a][1]=max(f[a][1],i-j);  
            b[a][0]=min(b[a][0],i+j); b[a][1]=min(b[a][1],i-j);  
        }  
    }  
    int p,q,ans=0;  
    for(int i=0;i<s;i++,p=q){  
        scanf("%d",&q);  
        if(i){  
            int t1=f[p][0]-b[q][0];  
            int t2=f[q][1]-b[p][1];  
            int t3=f[p][1]-b[q][1];  
            int t4=f[q][0]-b[p][0];  
            ans=max(ans,max(t1,max(t2,max(t3,t4))));  
        }  
    }  
    printf("%d\n",ans);  
    return 0;  
}  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值