NOIP2014提高组DAY1题解

T1:生活大爆炸版石头剪刀布

考察知识:模拟

算法难度:X+ 实现难度:XX

分析:

按照题目描述模拟即可,代码应该很易懂的:

#include
#include
#include
using namespace std;
int n,na,nb,a[205],b[205],A,B;
int calc(int x,int y){//所有情况
    if(x==0) switch(y){
        case 2:case 3: return 1;
        default :return 0;
    }
    else if(x==1) switch(y){
        case 0:case 3: return 1;
        default :return 0;
    }
    else if(x==2) switch(y){
        case 1: case 4: return 1;
        default :return 0;
    }
    else if(x==3) switch(y){
        case 2: case 4: return 1;
        default :return 0;
    }
    else if(x==4) switch(y){
        case 0: case 1: return 1;
        default :return 0;
    }
}
int main(){
    scanf("%d%d%d",&n,&na,&nb);
    for(int i=0;i

T2:联合权值

考察知识:图论,树

算法难度:XXX 实现难度:XXX

讲解+代码:见https://blog.csdn.net/Hi_KER/article/details/79761399

我半年前写的,还是勉强能看懂的。

T3:飞扬的小鸟

考察知识:动态规划,动态规划的优化

算法难度:XXX+ 实现难度:XXX+

分析:

定义状态方程:f(i,j)表示小鸟飞到坐标(i,j)需要的最少点击次数

边界:f(0,j)=0\,\,(0<j<=n) \,\,\,\,f(i,j)=\infty \,\,(i>0)

状态转移方程:f(i,j)=min\begin{Bmatrix} f(i-1,j+Y_i)&& \\ f(i-1,j-X_i\times c)&& \end{Bmatrix}

代码实现:

1.这种方法是用当前状态推后面状态,时间复杂度O(nmc),超时,80分

    for(int i=0;iY[i]) f[i+1][h-Y[i]]=min(f[i][h],f[i+1][h-Y[i]]);
        for(int c=1;;c++){
            if(h+c*X[i]>=m){
                f[i+1][m]=min(f[i+1][m],f[i][h]+c);
                break;
            }
            f[i+1][h+c*X[i]]=min(f[i+1][h+c*X[i]],f[i][h]+c);
        }
    }

2.背包优化

代码实现比方法1复杂,时间复杂度O(nm),可以AC

#include
#include
#include
using namespace std;
const int maxn=10002,inf=16000000;
int n,m,k,f[10002][2002/*注意*/],X[maxn],Y[maxn],L[maxn],H[maxn];
bool pipe[maxn];
void ready(){//预处理
    int pos,l,h;
    memset(f,1,sizeof(f));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%d%d",X+i,Y+i),H[i]=m+1;
    for(int i=1;i<=k;i++) scanf("%d%d%d",&pos,&l,&h),L[pos]=l,H[pos]=h,pipe[pos]=true;
    for(int i=1;i<=m;i++) f[0][i]=0;
}
void dp(){
    for(int i=1;i<=n;i++) {
        for(int h=X[i]+1;h<=m+X[i];h++)
          f[i][h]=min(f[i-1][h-X[i]],f[i][h-X[i]])+1;//刷表
        for(int h=m+1;h<=m+X[i];h++)//处理高度超过m的情况
          f[i][m]=min(f[i][m],f[i][h]);
        for(int h=1;h<=m-Y[i];h++)//处理不按屏幕的情况
          f[i][h]=min(f[i-1][h+Y[i]],f[i][h]);
        for(int h=1;h<=L[i];h++) f[i][h]=inf;//有水管的地方不能达到,所以inf
        for(int h=H[i];h<=m;h++) f[i][h]=inf;
    }
    int ans=inf;
    for(int i=1;i<=m;i++) ans=min(ans,f[n][i]);
    if(ans=0;i--){
        for(int h=L[i]+1;h<=H[i]-1;h++) if(f[i][h]

 

你可能感兴趣的:(竞赛考试,NOIP提高组历年考试)