A. Dima and Guards
只需要比较一下,守卫的最小要求的和与给定值的大小即可
#include<iostream>
#include<cstdio>
using namespace std;
int n,x1,y1,x2,y2;
int who,choc,juice;
bool can(int x,int y)
{
return x+y<=n;
}
int main()
{
cin>>n;
bool flag=false;
for(int i=1;i<=4;i++)
{
cin>>x1>>y1>>x2>>y2;
if(!flag)
{
if(can(x1,x2)){choc=x1,juice=n-choc;flag=true;}
else if(can(x1,y2)){choc=x1;juice=n-choc;flag=true;}
else if(can(y1,x2)){choc=y1;juice=n-choc;flag=true;}
else if(can(y1,y2)){choc=y1,juice=n-choc;flag=true;}
if(flag) who=i;
}
}
if(flag)
cout<<who<<" "<<choc<<" "<<juice<<endl;
else cout<<-1<<endl;
return 0;
}
B. Dima and To-do List
表示没太看懂。。。只需要从1到k循环就行了
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=100010;
const int INF=1000000000;
int a[2*maxn];
int N,K;
int main()
{
scanf("%d%d",&N,&K);
for(int i=1;i<=N;i++)
scanf("%d",&a[i]);
int max1=INF,sum=0,ans;
for(int i=1;i<=K;i++)
{
sum=0;
for(int j=0,k=i;j<N/K;k+=K,j++)
{
sum+=a[k];
}
if(sum<max1){max1=sum,ans=i;}
}
cout<<ans<<endl;
}
C. Dima and Salad
没想到需要这样变形,看了别人的题解,才明白过来
题意:就是给了你两个数组:a数组和b数组,然后让你从a数组中选取一个的子序列,子序列的和为sum1,然后除以相应b数组子序列的和sum2,sum1/sum2刚好为k,让你求出满足要求的a数组中sum1最大为多少,如果不存在这样的子序列,那么就输出-1,否则输出a数组中最大的sum1。
分析:对于这道题,我感悟还是比较深的,当时我想到用dp去做,并且抓住了两个数组加起来的和分别最多为10000,当时我没有把题目中的那个式子做变形,所以只想到了去记录a数组子序列相加之后的状态,但是如果a数组子序列的一个状态对应有多个b数组序列的状态呢?想到了这里,我就没法想下去了,因为我无法想到一个好的方法去解决这个问题,后来比完赛之后去看了下别人的代码,他们是把式子变形之后,把a[i]-b[i]*k作为状态进行dp的,这样a数组的序列和b数组的序列就绑定在一起了,就没必要去考虑我出现的问题了,而他的状态变化范围是:-10000-10000,出现了为负数的状态,无法用数组实现,于是干脆把所有状态都加上10000,于是状态的变化范围就变成:0-20000,那么现在就可以在此基础上进行dp了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 300005
#define mod 1000000007
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
int n,m,ans,k,flag,cnt;
int a[maxn],b[maxn];
int w[maxn];
int dp[MAXN];
bool solve()
{
int i,j;
memset(dp,-INF,sizeof(dp));
dp[10000]=0;
for(i=1; i<=n; i++)
{
if(w[i]>=0)
{
for(j=20000; j>=w[i]; j--)
{
if(dp[j-w[i]]!=-INF) dp[j]=max(dp[j],dp[j-w[i]]+a[i]);
}
}
else
{
for(j=0;j<20000;j++)
{
if(dp[j-w[i]]!=-INF) dp[j]=max(dp[j],dp[j-w[i]]+a[i]);
}
}
}
ans=dp[10000];
if(ans==0) return false ;
return true ;
}
int main()
{
int i,j;
while(~scanf("%d%d",&n,&k))
{
for(i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
for(i=1; i<=n; i++)
{
scanf("%d",&b[i]);
}
for(i=1; i<=n; i++)
{
w[i]=a[i]-k*b[i];
}
if(solve()) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
D. Dima and Trap Graph
思路:枚举每条边,并查集维护,每次加进去右端点大的边判断1和n是不是已联通,更新最大值
下面是并查集的代码:
这个题看人家写的还可以枚举左端点,二分右顶点,dfs判断。
下面是代码:
思路:枚举每条边,并查集维护,每次加进去右端点大的边判断1和n是不是已联通,更新最大值
下面是并查集的代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxm=3010;
const int maxn=1010;
struct node
{
int a,b,l,r;
};
int pre[maxn];
int n,m;
bool cmp(node a,node b)
{
return a.r>b.r;
}
void init()
{
for(int i=0;i<=n;i++)
{
pre[i]=i;
}
}
int find(int x)
{
if(pre[x]==x) return x;
return pre[x]=find(pre[x]);
}
void unite(int a,int b)
{
int x=find(a);
int y=find(b);
pre[x]=y;
}
int main()
{
node edge[maxm];
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
cin>>edge[i].a>>edge[i].b>>edge[i].l>>edge[i].r;
sort(edge,edge+m,cmp);
int ans=-1;
for(int i=0;i<m;i++)
{
init();
int min1=edge[i].r;
for(int j=0;j<m;j++)
{
if(edge[j].l>edge[i].l) continue;
unite(edge[j].a,edge[j].b);
min1=min(min1,edge[j].r);
int x=find(1);
int y=find(n);
if(x==y) {ans=max(ans,min1-edge[i].l+1);break;}
}
}
if(ans<=0)
cout<<"Nice work, Dima!"<<endl;
else
cout<<ans<<endl;
return 0;
}
这个题看人家写的还可以枚举左端点,二分右顶点,dfs判断。
下面是代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 1005
#define MAXN 100005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m,ans,cnt,ii,cxx,flag;
int pp[MAXN];
bool vis[MAXN];
int x[MAXN];
struct Node
{
int v,next;
int a,b;
} edge[MAXN];
void addedge(int u,int v,int a,int b)
{
cnt++;
edge[cnt].v=v;
edge[cnt].a=a;
edge[cnt].b=b;
edge[cnt].next=pp[u];
pp[u]=cnt;
}
void dfs(int u,int le,int ri)
{
if(flag) return ;
if(u==n)
{
flag=1;
return ;
}
int i,j,v;
for(i=pp[u]; i; i=edge[i].next)
{
v=edge[i].v;
if(!vis[v]&&le>=edge[i].a&&ri<=edge[i].b)
{
vis[v]=1;
dfs(v,le,ri);
}
}
}
void solve()
{
int i,j,u,v,t;
int le,ri,mid;
ans=0;
for(i=1;i<=cxx;i++)
{
le=x[i],ri=1000001;
while(le<ri)
{
mid=(le+ri)>>1;
flag=0;
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs(1,x[i],mid);
if(flag) le=mid+1;
else ri=mid;
}
ans=max(ans,le-x[i]);
}
}
int main()
{
int i,j;
int u,v,a,b;
while(~scanf("%d%d",&n,&m))
{
cnt=cxx=0;
memset(pp,0,sizeof(pp));
for(i=1; i<=m; i++)
{
scanf("%d%d%d%d",&u,&v,&a,&b);
x[++cxx]=a;
x[++cxx]=b;
addedge(u,v,a,b);
addedge(v,u,a,b);
}
solve();
if(ans) printf("%d\n",ans);
else printf("Nice work, Dima!\n");
}
return 0;
}