Codeforces #480 (Div. 2) 解题报告 B Marlin 构造

题解:

1、一个矩形小镇(4行奇数列)上左上角的村庄要到右下角的鱼塘,左下角的村庄要到右上角的鱼塘,问相同数量的最短路径是否存在,并输出构造正确的小镇形状

2、观察数据范围可以得知恒存在YES答案,因为K的值永远小于等于矩形的内层

3、为了简化构造,我们可以认为左上角要去右下角,右上角要去左下角

4、第一种情况是酒店数量是偶数的情况直接在二三层相等数量相同列放置即可

5、第二种情况是酒店数量小于等于列宽减2,那么只需一行即可完全放置所有酒店,但要注意对称放置,所以我从中间向两边放置(可删除)

6、第三种情况是酒店数量对4取模,4是表示二三层两边平均放置。模只有1或3,那么模出来(多出来)的酒店就先放置在中间某一层即可

7、答案恒输出YES,然后就是按照上面意思构造酒店位置即可

#include <iostream>
#include <string>
using namespace std;
const int maxn = 200;
char str[maxn][maxn];
int main(){
    int n,k;
    cin >> n >> k;
    for(int i=0;i<n;i++)
        for(int j=0;j<4;j++)
            str[j][i] = '.';
    if(k%2==0){  //偶数个酒店时直接从左往右排即可
        int t = k/2;
        for(int i=1;t>0;i++,t--){
            str[1][i] = '#';
            str[2][i] = '#';
        }
    }
    else if(k<=n-2){  //酒店数量小于等于列宽减2时表示一行可以放完所有酒店(本情况可删除)
        int t = k/2;  //但是要注意酒店的对称分布
        str[1][n/2] = '#';
        for(int i=1;t>0;i++,t--) {
            str[1][n/2+i] = '#';
            str[1][n/2-i] = '#';
        }
    }
    else if(k%4==1){  //两行都要放酒店时考虑4的余数放在中间单行放置(构造拱形)
        int t = k/4;
        str[1][n/2] = '#';
        for(int i=1;t>0;i++,t--) {
            str[1][n/2+i] = '#';
            str[1][n/2-i] = '#';
            str[2][n/2+i] = '#';
            str[2][n/2-i] = '#';
        }
    }
    else if(k%4==3){  //同上
        int t = k/4;
        str[1][n/2] = '#';
        str[1][n/2+1] = '#';
        str[1][n/2-1] = '#';
        for(int i=1;t>0;i++,t--) {
            str[1][n/2+i+1] = '#';
            str[1][n/2-i-1] = '#';
            str[2][n/2+i+1] = '#';
            str[2][n/2-i-1] = '#';
        }
    }
    cout << "YES" << endl;
    for(int i=0;i<4;i++){
        str[i][n] = '\0';  //char字符数组的结束标志
        cout << str[i] << endl;
    }
    return 0;
}

修改:今天上课时发呆突然想到第二种情况在数据范围内(主要考虑k=1以及k=3的时候)可以直接被包含在第三种情况内,所以以上第二种情况可以直接删掉,然后我再对重复代码进行一点删减。

#include <iostream>
#include <string>
using namespace std;
const int maxn = 200;
char str[maxn][maxn];

int main(){
    int n,k;
    cin >> n >> k;
    for(int i=0;i<n;i++)
        for(int j=0;j<4;j++)
            str[j][i] = '.';
    if(k%2==0){            //偶数个酒店时直接从左往右排即可
        int t = k/2;
        for(int i=1;t>0;i++,t--){
            str[1][i] = '#';
            str[2][i] = '#';
        }
    }
    else {                 //两行都要放酒店时考虑4的余数放在中间单行放置(构造拱形)
        int t = k/4,i = 1; //默认拱形中间长度为1
        str[1][n/2] = '#'; //提前放置必定存在的拱形中心
        if(k%4==3) {       //余数为三时修改拱形中间长度为3
            str[1][n/2+1] = '#';
            str[1][n/2-1] = '#';
            i = 2;         //控制拱形两边的起始位置
        }
        for(;t>0;i++,t--) {
            str[1][n/2+i] = '#';
            str[1][n/2-i] = '#';
            str[2][n/2+i] = '#';
            str[2][n/2-i] = '#';
        }
    }
    cout << "YES" << endl;
    for(int i=0;i<4;i++){
        str[i][n] = '\0';  //char字符数组的结束标志
        cout << str[i] << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a912952381/article/details/80253975