2019/11/29 CF-1263-B PIN Codes

Codeforces Round #603 (Div. 2)

题目链接:http://codeforces.com/contest/1263/problem/B

题意:

        t组测试样例(1≤t≤100),每组n个4位数的字符串(2≤n≤10),经过最少多少次变换后可以变成全部不一样。输出变换次数和变换后的字符串。如果有多组最佳答案,输出任意一组。

测试样例:

input
3
2
1234
0600
2
1337
1337
4
3139
3139
3139
3139
output
0
1234
0600
1
1337
1237
3
3139
3138
3939
6139

思路:

        要使一个四位字符串和别的完全不同,又要最小变换次数,仅仅需要改变其中一位就可以了。理论上可以改变任意一位,但我选择改变首位或末位,这样比较方便。

注意:

        跑给定的测试样例时可能输出的改变后的字符串和给定的输出样例不一样。这是因为题目并未对改变形式作出限定。不限定变了之后的字符串应该是怎么样的,只限定用最少变换次数变成全部不一样就行了。

 AC代码1:

        从数字角度出发,输入过程中标记出现过的数,然后双重for循环向前扫描是否有与当前数相同的数字,如果有,一直改变它直到变为未出现过的数字,将改变后的数字继续进行标记。因为是字符串所以首位可以是0,当不足四位时首位补零输出即可。

#include<bits/stdc++.h>
using namespace std;
bool vis[10000];//标记出现过的数字
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int a[10];
        scanf("%d",&n);
        int cnt=0;
        memset(vis,0,sizeof(vis));//初始化标记数组
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            vis[a[i]]=1;
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<i;j++)
                if(a[i]==a[j])
                {
                    while(vis[a[i]])
                        a[i]=(a[i]+1000)%10000;//改变数字第一位,若为三位数,输出时首位补零
                    vis[a[i]]=1;//标记改变后的数字
                    cnt++;
                    break;
                }
        printf("%d\n",cnt);
        for(int i=0;i<n;i++)
            printf("%04d\n",a[i]);//以4位数输出,不足四位首位补0
    }
    return 0;
}

AC代码2:

          运用字符串,输入过程中标记每个字符串最后一位字符。然后双重for循环向前扫描是否有与当前字符串相同的字符串,如果有,就将当前字符串最后一位变为一个未被标记的字符,将用掉的字符继续进行标记。

#include<bits/stdc++.h>
using namespace std;
bool vis[10];//标记0-9十个字符
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,0,sizeof(vis));//初始化标记数组
        int n;
        scanf("%d",&n);
        char s[10][5];
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",s[i]);
            vis[s[i][3]-'0']=1;//标记字符串最后一位
        }
        //判断当前是否与前面的某一个相等,前面的一定是不重复的
        for(int i=0;i<n;i++)
            for(int j=0;j<i;j++)
                if(strcmp(s[i],s[j])==0)
                    for(int k=0;k<10;k++)//若相等,则找一个未被标记的替换掉最后一位
                        if(vis[k]==0)
                        {
                            s[i][3]=k+'0';
                            vis[k]=1;//继续标记
                            cnt++;
                            break;
                        }
        printf("%d\n",cnt);
        for(int i=0;i<n;i++)
            printf("%s\n",s[i]);
    }
    return 0;
}

        AC代码1和2都用了双重for循环遍历查找是否存在相同的,增加了时间复杂度。虽然都对这道题没有影响,但学长有更好的解法。

学长AC代码:

By siyiyimiaozhong, contest: Codeforces Round #603 (Div. 2), problem: (B) PIN Codes

#include <bits/stdc++.h>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
string s[20];
bool vis[20];
int n,x;
 
int main()
{
    SIS;
    int T,x;
    cin >> T;
    while(T--)
    {
        cin >> n;
        map<string,int> mp;
        for(int i=0;i<n;i++)
        {
            cin >> s[i];
            mp[s[i]]++;
        }
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            if(mp[s[i]]==1) continue;
            cnt++;
            mp[s[i]]--;
            for(char j='0';j<='9';j++)
            {
                s[i][0]=j;
                if(mp[s[i]]==0) 
                {
                    mp[s[i]]++;
                    break;
                }
            }
        }
        cout << cnt << endl;
        for(int i=0;i<n;i++)
            cout << s[i] << endl;
    }
    return 0;
}
发布了26 篇原创文章 · 获赞 1 · 访问量 445

猜你喜欢

转载自blog.csdn.net/qq_45309822/article/details/103328538