您的位置:首页 > 其它

【NOIP2014提高组】【Day1】【解题报告】

2015-10-19 18:51 459 查看
T1:生活大爆炸版石头剪刀布

题目链接:http://codevs.cn/problem/3716/

题解:预处理出两两之间的关系。直接模拟即可。

代码:

#include<iostream>
#include<cstdio>
using namespace std;
int ans1,ans2,t1,t2,c[30][30],n,l1,l2,a[501],b[501];
int main(){
c[0][2]=1;c[0][3]=1;
c[1][3]=1;c[2][4]=1;
c[3][4]=1;c[1][0]=1;
c[4][0]=1;c[2][1]=1;
c[4][1]=1;c[3][2]=1;
c[0][0]=-1;c[1][1]=-1;
c[2][2]=-1;c[3][3]=-1;
c[4][4]=-1;
cin>>n>>l1>>l2;
for (int i=1;i<=l1;i++) cin>>a[i];
for (int i=1;i<=l2;i++) cin>>b[i];
t1=1;t2=1;
for (int i=1;i<=n;i++){
if(c[a[t1]][b[t2]]>0)ans1++;
else if (c[a[t1]][b[t2]]!=-1) ans2++;
t1++;t2++;if (t1==l1+1) t1=1;
if (t2==l2+1) t2=1;
}
cout<<ans1<<' '<<ans2<<endl;
}
T2:联合权值

题目链接:http://codevs.cn/problem/3728/

题解:由数学公式可得2ab+2ac+2bc=(a+b+c)^2-a^2-b^2-c^2;

            然后枚举每个点,和这个相连的点两两之间一定能产生联合权值。

            代入那个公式直接算一下就好了。复杂度显然为O(n);

代码:

#include<iostream>
#include<cstdio>
#define N 200010
#define P 10007
using namespace std;
struct use{int st,en;}e[N*2];
long long ans,w
,maxx;
int cnt,n,a,b,point
,next[N*2];
void add(int x,int y){
next[++cnt]=point[x];point[x]=cnt;
e[cnt].st=x;e[cnt].en=y;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n-1;i++){scanf("%d%d",&a,&b);add(a,b);add(b,a);}
for (int i=1;i<=n;i++) scanf("%lld",&w[i]);
for (int i=1;i<=n;i++){
long long tp1(0),tp2(0),mx1(-1),mx2(-1);
for (int j=point[i];j;j=next[j]){
(tp1+=w[e[j].en])%=P;(tp2+=w[e[j].en]*w[e[j].en])%=P;
if (mx1<w[e[j].en]){mx2=mx1;mx1=w[e[j].en];}
else mx2=max(mx2,w[e[j].en]);
}
(ans+=(tp1*tp1)%P-tp2+P)%=P;maxx=max(maxx,mx1*mx2);
}
cout<<maxx<<' '<<ans<<endl;
}
T3飞扬的小鸟

题目链接:http://codevs.cn/problem/3729/

题解:设f[i][j]为从第0列走到(i,j)的最小步数.

             显然 f[i][j]=max(f[i-1][j+y[i-1]],f[i-1][j-k*x[i-1]]+k);

          这样直接转移显然是O(n*m*k)的。可以得到70分。

          观察一下后半部分.可以发现是完全背包。

          然后用完全背包优化一下就成了O(n*m).足以通过全部的数据。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 10010
#define inf 707406378
using namespace std;
int x
,y
,up
,down
,f
[1010],n,m,k,p,ans;
int main(){
scanf("%d%d%d",&n,&m,&k);up
=m+1;down
=0;
for (int i=0;i<n;i++) {scanf("%d%d",&x[i],&y[i]);up[i]=m+1;down[i]=0;}
for (int i=1;i<=k;i++){scanf("%d",&p);scanf("%d%d",&down[p],&up[p]);}
memset(f,127/3,sizeof(f));
for (int i=1;i<=m;i++) f[0][i]=0;
for (int i=1;i<=n;i++){
for (int j=x[i-1];j<=m;j++){
f[i][j]=min(f[i][j],f[i-1][j-x[i-1]]+1);
f[i][j]=min(f[i][j],f[i][j-x[i-1]]+1);
}
for (int j=m-x[i-1];j<=m;j++){
f[i][m]=min(f[i][m],f[i-1][j]+1);
f[i][m]=min(f[i][m],f[i][j]+1);
}
for (int j=down[i]+1;j<=up[i]-1;j++){
if (j+y[i-1]<=m) f[i][j]=min(f[i][j],f[i-1][j+y[i-1]]);
}
for (int j=1;j<=down[i];j++) f[i][j]=inf;
for (int j=up[i];j<=m;j++) f[i][j]=inf;
}ans=inf;int t=k;
for (int i=n;i>=1;i--){
for (int j=down[i]+1;j<up[i];j++) ans=min(ans,f[i][j]);
if (ans!=inf) break;if (up[i]!=m+1) t--;
}
if (t==k){cout<<1<<endl<<ans<<endl;}
else{cout<<0<<endl<<t<<endl;}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: