【题解】Educational Codeforces Round 73 (Rated for Div. 2)

  • A. 2048 Game(思维)
  • B. Knights(构造)
  • C. Perfect Team(模拟)
  • D. Make The Fence Great Again(二维dp)


A. 2048 Game(思维)

原题链接:http://codeforces.com/contest/1221/problem/A

  • 题意: 2048游戏,有玩过的都懂。给你一列数字,都是2的次幂,这个数列中相同的数可以互相相加,相加之后两个加数去掉,把和放入数列。之后数列中相同的数字又可以相加。问这个数列在变换中有没有可能出现2048。

  • 思路: 比赛时想复杂了,两层循环实现,具体看代码吧,仅供参考!看了大佬的思路和代码才发现这题可以写得很简单。因为所有数都是 2 的次幂且 1+2+4…+1024 全部都只有一个,也只有2047,所以只要确保小于等于2048的数字相加后能大于等于2048即可。


Code1: 比赛时的代码,把所有情况考虑了一遍,代码看起来可能有点复杂。

#include 
#include 
using namespace std;
typedef long long ll;
ll a[105];
int main(){
    int t;  cin>>t;
    while(t--){
        int n;  cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        int vis=0;
        int flag=1;
        for(int i=1;i<=n;i++){
            ll sum=a[i];
            if(a[i]==2048){
                vis=1;
                break;
            }
            for(int j=i+1;j<=n;j++){
                if(a[j]<2048){
                    sum+=a[j];
                    if(sum==2048){
                        vis=1;
                        break;
                    }
                    else if(sum>2048)   break;
                }
                else if(a[j]>2048){
                    flag=0;
                    break;
                }
                else{
                    vis=1;
                    break;
                }
            }
            if(vis) break;
            if(!flag)   break;
        }
        if(!flag){
            cout<<"NO"<<endl;
            continue;
        }
        if(vis) cout<<"YES"<<endl;
        else    cout<<"NO"<<endl;
    }
    return 0;
}

Code2:

#include 
using namespace std;
int main(){
    int q;  cin>>q;
    while(q--){
        int n;  cin>>n;
        int sum=0,x;
        for(int i=1;i<=n;i++){
            cin>>x;
            if(x<=2048) sum+=x;
        }
        if(sum>=2048)   cout<<"YES"<<endl;
        else    cout<<"NO"<<endl;
    }
    return 0;  
}


B. Knights(构造)

原题链接:http://codeforces.com/contest/1221/problem/B

  • 题意: 要在一个n*n的棋盘中放满黑方和白方的马,马走 ‘日’ 字,求出最优方案使得双方所有马的攻击次数最多。

  • 思路: 奇数行奇数列和偶数行偶数列放白马,其他放黑马。


Code:

#include 
using namespace std;
int main(){
    int n;  cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if((i%2==1&&j%2==1) || (i%2==0&&j%2==0))
                cout<<'W';
            else
                cout<<'B';
        }
        cout<<endl;
    }
    return 0;
}


C. Perfect Team(模拟)

原题链接:http://codeforces.com/contest/1221/problem/C

  • 题意: a,b,c 三种人各 c,m,x 个,要求 3 人一队且每队必须至少有 a,b 各一个,问最多能组成多少队。

  • 思路: 因为 c,m 至少要有一个,所以取 c,m 较小值,然后乘以 3 与 c,m,x 三数之和比较。如果比总数大,说明 c,m 是充足的,所以只需要输出总数除以 3 的结果即可;如果小于等于总数,说明总数是充足的,所以只需输出 c,m 较小值乘以 3 的结果。


Code:

#include 
using namespace std;
typedef long long ll;
int main(){
    int q;  cin>>q;
    while(q--){
        ll c,m,x;
        cin>>c>>m>>x;
        ll minn=min(c,m);
        if(c+m+x>=3*minn)
            cout<<minn<<endl;
        else
            cout<<(c+m+x)/3<<endl;
    }
    return 0;
}


D. Make The Fence Great Again(二维dp)

原题链接:http://codeforces.com/contest/1221/problem/D

  • 题意: 给你 n 个格子的高度和提高该格子一个单位高度所需花费的价格,每个格子最多提高两点高度,问使得所有相邻格子不同高度时所需的最小花费。

  • 思路: 用二维数组 dp[i][j] 表示格子提高相应的高度所需的花费,j 有三种状态,分别为 0,1,2,然后三层循环遍历,不断地寻找相邻格子高度不相同时三种状态所需的最小花费,最后输出三种状态高度不相同时的最小花费。要注意的就是最后输出的时候要取消同步,否则会TLE。


Code:

#include 
using namespace std;
typedef long long ll;
const ll inf=2e18;
const int N=3e5+10;
ll dp[N][3],a[N],b[N];
int main(){
    ios::sync_with_stdio(0);    //要取消同步才不会TLE
    int t;  cin>>t;
    while(t--){
        int n;  cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i]>>b[i];
            dp[i][0]=dp[i][1]=dp[i][2]=inf;
        }
        dp[1][0]=0; //第一个格子
        dp[1][1]=b[1];
        dp[1][2]=2*b[1];
        for(int i=2;i<=n;i++){
            for(int j=0;j<3;j++){
                for(int k=0;k<3;k++){
                    if(a[i-1]+j!=a[i]+k)    //如果相邻格子高度不相同
                        dp[i][k]=min(dp[i][k],dp[i-1][j]+k*b[i]);   //取花费小的
                }
            }
        }
        //取三种状态花费最小的
        cout<<min(dp[n][0],min(dp[n][1],dp[n][2]))<<endl;
    }
    return 0;
}


你可能感兴趣的:(【题解】Educational Codeforces Round 73 (Rated for Div. 2))