11.5模拟

3 篇文章 0 订阅
2 篇文章 0 订阅

100+40+100=240
为毛t3正解了, t2才40?

T1.名字排序(name)

【问题描述】
给定 n 个字符串,请去重后按照字典序排序
【输入格式】 从文件 name.in中读入数据。 输入的第一行包含两个正整数 n 表示总数
,接下来 n行有 n 个字符串。
【输出格式】
第一行输出去重后的字符串个数 X
接下来 x 行按照字典序输出每一个字符串
【样例 1 输入】
4
a
ab
cdef
ejdeh
【样例 1 输出】
4
a
ab
cdef
ejdeh
对于 20%的数据保证不需要去重
对于 100%的数据 n<=100000;单个字符串长度小于 10。

水题(划掉),STL搞一搞就好啦。qwq
1.字符串排序自动为字典序,无需定义。
2.巩固了一下STL。

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
vector<string> a;
string aa;
int ans,n;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)cin>>aa,a.push_back(aa);
    sort(a.begin(),a.end());
    vector<string>::iterator new_end;
    new_end=unique(a.begin(),a.end());
    for(vector<string>::iterator i=a.begin();i!=new_end;i++)ans++;printf("%d\n",ans);
    for(vector<string>::iterator i=a.begin();i!=new_end;i++)cout<<*i<<endl; 
}

另一种水法——Taunt大佬

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

const int maxn = 100000 + 100;
string ch[maxn];
int n,ans = 0;

int main() {
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) cin>>ch[i];
    sort(ch+1,ch+1+n);
    for(int i = 1; i <= n; i++)
        if(ch[i] != ch[i-1]) ans++;
    cout<<ans<<endl;
    for(int i = 1; i <= n; i++) {
        if(ch[i] == ch[i-1]) continue;
        cout<<ch[i]<<endl;
    }
    return 0;
}

超快的水法

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct rt
{
    char a[20];
};
rt que[100001];
bool cmp(rt x,rt y)
{   
    int judge;
    judge=strcmp(x.a,y.a);
    if(judge<0) judge=1;
    else judge=0;
    return judge;
}
int main()
{
    int n,ans=0;    
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%s",que[i].a);
    sort(que+1,que+n+1,cmp);
    for(int i=1;i<=n;i++)
    {   
        if(strcmp(que[i-1].a,que[i].a)==0) continue;
        else ans++;
    }
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)
        if(strcmp(que[i-1].a,que[i].a)==0) continue;
        else printf("%s\n",que[i].a);
    return 0;
}

T2.大吉大利(jiry)

【问题描述】
“大吉大利,晚上吃鸡!”
牛牛最近迷上了《绝地求生 大逃杀》这款游戏。他恨不能每天都吃鸡。但是他的舍友还
在王者峡谷等着他开黑。然而牛牛的心中只有一件事,那就是学习。
现在共有 n 天,每天都有一个数字 i,具体含义如下:
0 牛牛不能吃鸡也不能玩农药
1 牛牛可以吃鸡但不能玩农药
2 牛牛不可以吃鸡但可以玩农药
3 牛牛可以吃鸡或者玩农药
每天只能选择吃鸡、玩农药、学习中的一件事,并且牛牛不能连续两天吃鸡也不能连续两
天玩农药。请求出牛牛最大的学习的总天数。
【输入格式】 从文件 jiry.in中读入数据。 输入的第一行包含两个正整数 n 表示总天数。
接下来 n 行,每行包含 1个数字 i
【输出格式】输出到文件 jiry.out 中。输出一个牛牛最多学习的总天数。
【样例 1 输入】

7
1 3 3 2 1 2 3
【样例 1 输出】
0
【样例 2 输入】
2
2 2
【样例 2 输出】
1
【样例 3 输入】
4
1 3 2 0
【样例 3 输出】
2

//改编题,来自cf698A
我的贪心(40)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int maxn=101;
int a[maxn],n,ans;
int main()
{
    scanf("%d",&n); a[0]=233;
    for(int i=1;i<=n;i++)   scanf("%d",&a[i]);
    int x=1;    while(a[x]==3) x++;
    for(int i=x;i<=n;i++)if(a[i]==3){
        if(a[i-1]==1) a[i]=2;
        if(a[i-1]==2) a[i]=1;
    }
    for(int i=x;i<=n;i++) if((a[i]==0)||(a[i]==a[i-1])) ans++;
    printf("%d",ans);
}

改(100):

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=101;
int a[maxn],ans,n;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        if(a[i]==0) ans++;
        else if(a[i]==a[i-1]&&a[i]!=3)  ans++,a[i]=0;
        else if(a[i]==3){
            if(a[i-1]==0||a[i-1]==3) a[i]==0;
            else if(a[i-1]==1)  a[i]=2;
            else if(a[i-1]==2)  a[i]=1;
        }
    }
    printf("%d",ans);
    return 0;
}

DP:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 233;
int n,f[maxn][10];   // 0 study 1 wangzhe 2 ji

int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * f;
}

int main() {
    n = read();
    for(int i = 0; i <= n; i++) {
        for(int j = 0; j <= 2; j++) 
            f[i][j] = 1<<29;
    }
    f[0][0] = 0;
    for(int i = 1; i <= n; i++) {
        int a = read();
        if(a == 1 || a == 3) {
            f[i][2] = min(f[i - 1][1], f[i][2]);
            f[i][2] = min(f[i - 1][0], f[i][2]);    
        }
        if(a == 2 || a == 3) {
            f[i][1] = min(f[i - 1][2], f[i][1]);
            f[i][1] = min(f[i - 1][0], f[i][1]);
        }
        f[i][0] = min(f[i - 1][2] + 1,f[i][0]);
        f[i][0] = min(f[i - 1][0] + 1,f[i][0]);
        f[i][0] = min(f[i - 1][1] + 1,f[i][0]);
    }
    int ans = 1<<29;
    ans = min(ans,f[n][0]);
    ans = min(ans,f[n][1]);
    ans = min(ans,f[n][2]);
    cout<<ans<<endl;
    return 0;
}

电话线(line)

多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨
是负责接到震中市的负责人。该市周围分布着 N(1<=N<=1000)根据 1……n 顺序编号的废弃
的电话线杆,任意两根线杆之间没有电话线连接,一共有 p(1<=p<=10000)对电话杆可以拉
电话线。其他的由于地震使得无法连接。

第 i 对电线杆的两个端点分别是 ai,bi,它们的距离为 li(1<=li<=1000000)。数据中每对
(ai,bi)只出现一次。编号为 1的电话杆已经接入了全国的电话网络,整个市的电话线全都
连到了编号 N 的电话线杆上。也就是说,笨笨的任务仅仅是找一条将 1 号和 N 号电线杆连起
来的路径,其余的电话杆并不一定要连入电话网络。
电信公司决定支援灾区免费为此市连接 k 对由笨笨指定的电话线杆,对于此外的那些电话
线,需要为它们付费,总费用决定于其中最长的电话线的长度(每根电话线仅连接一对电话
线杆)。如果需要连接的电话线杆不超过 k 对,那么支出为 0.
请你计算一下,将电话线引导震中市最少需要在电话线上花多少钱?
输入输出格式
输入格式:
输入文件的第一行包含三个数字 n,p,k;
第二行到第 p+1行,每行分别都为三个整数 ai,bi,li。
输出格式:
一个整数,表示该项工程的最小支出,如果不可能完成则输出-1.
输入输出样例
输入样例#1:
5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
输出样例#1:
4

//usaco原题
正解是二分+spfa最短路
本来想写二分+去环lca的,模拟了一下果断gg
具体的,套俩模板就好了,
1.二分答案l=0,r=max(最长边)
2.spfa跑mid,找出最短路径里,第k+1大的边与二分答案的关系,return调整边界就好(细节就是把大于二分答案的边看做1,小于二分答案的边看做0)
3.别把二分跑死循环了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=1e3+10;
const int maxp=1e4+10;
const int maxl=1e6;
const int inf=1<<29;
int n,p,k,li,ri,mid,ans,head[maxn],tot,dis[maxn],vis[maxn];
int read(){
    int t=1,x=0;    char ch=getchar();
    while(ch>'9'||ch<'0'){  if(ch=='-')t=-1; ch=getchar();  }
    while(ch<='9'&&ch>='0'){ x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return t*x;
}
struct edge{
    int u,v,w,next;
}e[maxp<<1];
void add(int x,int y,int z){ e[++tot]=(edge){ x,y,z,head[x]};   head[x]=tot;}
bool spfa(int x){
    memset(dis,0x3f3f3f3f,sizeof(dis)); memset(vis,0,sizeof(vis));
    dis[1]=0;   vis[1]=1;
    queue<int> q;   q.push(1);
    while(!q.empty()){
        int now=q.front(); q.pop(); vis[now]=0;
        for(int i=head[now];i;i=e[i].next){
            int vv=e[i].v;
            if(e[i].w<=mid&&dis[vv]>dis[now]){//注意松弛条件1
                dis[vv]=dis[now];
                if(!vis[vv]){
                    vis[vv]=1;  q.push(vv);
                }
            }
            if(e[i].w>mid&&dis[vv]>dis[now]+1){//松弛条件2
                dis[vv]=dis[now]+1;
                if(!vis[vv]){
                    vis[vv]=1;  q.push(vv);
                }
            }
        }
    }
    return dis[n]<=k;
}
int main(){
    n=read(); p=read(); k=read();
    for(int i=1;i<=p;i++){
        int a=read(),b=read(),c=read();
        add(a,b,c); add(b,a,c);
    }
    li=0,ri=maxl,ans=-1;
    while(li<=ri){//二分答案即第k大边 
        mid=(li+ri)>>1;
        if(spfa(mid)) ans=mid,ri=mid-1;
        else li=mid+1;
    }
    printf("%d",ans);   return 0;
}
//松弛条件1:当前边权小于二分答案,记为0,然后松弛
//松弛条件2:当前边权大于二分答案,记为1,然后松弛
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值