第1题:生活大爆炸版石头剪刀布
题意:规则在石头剪刀布的基础上增加斯波克和蜥蜴人,总而言之,每种属性多了一个克星。
思路:(强模拟)
但我还是做的太慢了(花了30分钟)。
第2题:联合权值
题意:无向连通图G有n个点,n-1条边,每个点上有权值w,每条边长度均为1。若 两点的距离为2,则它们之间会产生Wi*Wj的联合权值。
求最大的联合权值及联合全值之和。其和对10007取余。
思路:很简单,找两个点的中间那个点即可,sum维护中间点到其它点的权值之和。计算时就减去该点即可。
第3题:飞扬的小鸟
题意: 就是点击屏幕穿过水管的小鸟。简单化,n*m的平面,有k个水管,每个水管有3个属性,x,L,H。还有处在X=i时,up一次增加的高度UPi和down一次下降的高度DOWNi。(在同一单位时间内可点击多次)。
思路:这真是教课书版的dp(小c),然而dp还是没有时间debug(我也不知道是为什么…)。当然,此dp可以在完全背包的基础上,优化成滚动dp。(也很明显,这一列只与上一列有关)。
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define LL long long
#define INF 0x3f3f3f3f
#define N 10005
#define M 1005
using namespace std;
int n,m,k,a,b,c;
int up[N],down[N],Sum[N];
struct node{
int L,H;
}W[N];
bool mark[N];
int dp[N][M];
void chk(int &x,int y){if(x==-1||x>y)x=y;}
struct P1{
void solve(){
REP(i,0,m)dp[0][i]=0;
int cur=1,Cnt=0;
REP(i,1,n){
memset(Sum,-1,sizeof(Sum));
memset(dp[cur],-1,sizeof(dp[cur]));
REP(j,W[i].L+1,W[i].H-1){
int y=j+down[i];
if(y>m)continue;
if(dp[!cur][y]!=-1)Sum[j]=dp[!cur][y];
}
REP(j,0,m){
int y=j+up[i];
if(y>m)y=m;
if(dp[!cur][j]!=-1)chk(dp[cur][y],dp[!cur][j]+1);
if(dp[cur][j]!=-1)chk(dp[cur][y],dp[cur][j]+1);
}
REP(j,0,m)if(Sum[j]!=-1)chk(dp[cur][j],Sum[j]);
REP(j,0,W[i].L)dp[cur][j]=-1;
REP(j,W[i].H,m)dp[cur][j]=-1;
bool f=0;
REP(j,W[i].L+1,W[i].H-1)if(dp[cur][j]!=-1)f=1;
cur^=1;
if(!f){
printf("0\n%d\n",Cnt);
exit(0);
}
if(mark[i])Cnt++;
}
int ans=1e9;
REP(j,W[n].L+1,W[n].H-1)if(ans>dp[!cur][j]&&dp[!cur][j]!=-1)ans=dp[!cur][j];
printf("1\n%d\n",ans);
}
}p1;
struct P2{
void solve(){
int Cnt=0;
memset(dp,-1,sizeof(dp));
REP(i,1,m)dp[0][i]=0;
REP(i,1,n){
memset(Sum,-1,sizeof(Sum));
REP(j,W[i].L+1,W[i].H-1){
int y=j+down[i];
if(y>m)continue;
if(dp[i-1][y]!=-1){
Sum[j]=dp[i-1][y];
}
}
REP(j,1,m){
int y=j+up[i];
if(y>m)y=m;
if(dp[i-1][j]!=-1)chk(dp[i][y],dp[i-1][j]+1);
if(dp[i][j]!=-1)chk(dp[i][y],dp[i][j]+1);
}
REP(j,1,m)if(Sum[j]!=-1)chk(dp[i][j],Sum[j]);
REP(j,1,W[i].L)dp[i][j]=-1;
REP(j,W[i].H,m)dp[i][j]=-1;
bool f=0;
REP(j,W[i].L+1,W[i].H-1)if(dp[i][j]!=-1)f=1;
if(!f){
printf("0\n%d\n",Cnt);
exit(0);
}
if(mark[i])Cnt++;
}
int ans=1e9;
REP(j,W[n].L+1,W[n].H-1){
if(ans>dp[n][j]&&dp[n][j]!=-1)ans=dp[n][j];
}
printf("1\n%d\n",ans);
}
}p2;
int main(){
srand(time(NULL));
scanf("%d%d%d",&n,&m,&k);
REP(i,1,n)scanf("%d%d",&up[i],&down[i]);
REP(i,1,n)W[i]=(node){0,m+1};
REP(i,1,k){
scanf("%d%d%d",&a,&b,&c);
mark[a]=1;
W[a]=(node){b,c};
}
int x=rand()%2;
if(x)p1.solve();
else p2.solve();
return 0;
}
小结:
感觉每次的考试是看似简单,实则连暴力分都没拿到(以后还是先切分),甚至直接爆0。所以还是先打完暴力就对拍,不急去想正解,稳拿到暴力分。