群赛地址;
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;
}