【60测试_联考2】【贪心】【模拟】【找规律_排序】

第一题:

  给你N个字符串 ,你每次 可以 选择 其中 一个 字符串 的一段 前缀 进行 翻转 ,但 是你必须 保证 这个 前缀 的长度 是偶数 。你可以 进行 无限次 这样 的操作 ,并且如果两个字符串 变得 相同 的时候 ,你就可以把这两个字符串都删除掉,问最后最少剩下多少个字符串 ?n<=50, t( t 组数据)<=11

解:  一直觉得这道题很神奇。写了好久的草稿,结果还是没看出来。其实根据偶数这个性质,只要再深入一点就可以发现了。无论如何翻转,原本相邻的 i 和 i+1 两个位置的字符是不会被拆开的,所以可以直接记录两个连着的字符。然后为了直观的判断,只需要以没两个字符的第一个字符为第一个关键字,第二个字符为第二个关键字将原字符串排序,排序后的状态肯定可以通过翻转得到,所以排完序后只要存在两个相同,那么这两个就符合条件。

  需要注意的是,只有两两之间才能删除,如果三个都可以,但是根据题意,在找到前两个后就被删了,因此不可能再匹配到第三个。

  赋初值,要清零。

  字符串(字母)的常用处理:转化为ASCII码记录。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define maxn 55
 6 using namespace std;
 7 struct pp{
 8     int one,two;
 9 };
10 pp s[maxn][maxn];
11 int n,t,num[maxn],ans;
12 bool vis[maxn];
13 const int comp(const pp&a,const pp&b)
14 {
15     if (a.one!=b.one) return a.one<b.one;
16     return a.two<b.two;
17 }
18 void chuli(int cur)
19 {
20     char c[maxn];
21     scanf("%s",c+1);
22     int len=strlen(c+1);
23     num[cur]=len;
24     for (int i=1;i<=len/2;i++)
25     {
26         s[cur][i].one=min(c[i*2-1]-'a'+1,c[i*2]-'a'+1);
27         s[cur][i].two=max(c[i*2-1]-'a'+1,c[i*2]-'a'+1);
28     }
29     if (len%2) {
30         s[cur][len/2+1].one=c[len]-'a'+1;
31         s[cur][len/2+1].two=0;
32     }
33     sort(s[cur]+1,s[cur]+len/2+1,comp);
34 }
35 void work()
36 {
37     ans=n;
38     for (int i=1;i<=n;i++)
39      for (int j=i+1;j<=n;j++)
40        if (!vis[j]&&!vis[i]&&num[i]==num[j]){
41               bool yes=false;
42               int l=num[i];
43               if (l%2) l=l/2+1;
44               else l/=2;
45               for (int k=1;k<=l;k++)
46                 if (s[i][k].one!=s[j][k].one||s[i][k].two!=s[j][k].two){
47                     yes=true;break;
48                 } 
49             if (yes) continue;
50             vis[i]=true;vis[j]=true;    
51             ans-=2;
52        }
53     printf("%d
",ans);
54 }
55 int main()
56 {
57     freopen("kahuucino.in","r",stdin);
58     freopen("kahuucino.out","w",stdout);
59     cin>>t;
60     while(t)
61     {
62         memset(s,0,sizeof(s));
63         memset(vis,0,sizeof(vis));//*****
64         scanf("%d",&n);
65         for (int i=1;i<=n;i++)
66             chuli(i);
67         work();
68         t--;
69     }
70     return 0;
71 }

第二题:

  对于每只怪有两个值:战斗值和能力值。它们相互打,只有战斗值高X的打死战斗值低的Y,并且打死后的战斗值变为:自己原来的战斗值-Y的战斗值+Y的能力值。问战斗后,怪中战斗值+能力值最大能达到多少。(对于每一只怪,不一定要把剩下的怪打完,想打谁打谁)

解:    这道题先开始根本没有读懂,以为必须把所有怪打完。。这道题用贪心做。把怪分为战斗型(负责打)和能力型(负责被打,因为打它获得正的战斗值)两种,然后将能力型按战斗值排序,战斗型按战斗值+能力值sum排序。对于某一个战斗值,可以恰好把能力型的所有怪打完(因为边打的时候战斗值会变大),这个战斗值为 “底线pos,在战斗型中第一个超过这个pos的怪即ans,因为战斗型按sum排序,而ans为战斗值+能力值,对于大于攻击值pos的所有战斗型怪能从能力值怪中获得的收益是相同的,所以只需比较这个sum,最靠前的即ans。当然,还有一种情况,就是用能力型中战斗值最大的一只打所有能力型怪,也可以获得很大的收益,将两者相比较得到ans。

  看来贪心还是不是很熟,排序很重要,怎么排,什么是最优解,满足什么条件,把这些都弄清楚,方法就出来了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define maxn 100005
 6 #define ll long long
 7 using namespace std;
 8 ll n,idi,idj,pos,s;
 9 struct pp{
10     ll fight,val;
11 };
12 pp abled[maxn];
13 struct oo{
14     ll fight,sum;
15 };
16 oo attack[maxn];
17 const ll comp1(const pp&a,const pp&b)
18 {
19     return a.fight<b.fight;
20 }
21 const ll comp2(const oo&a,const oo&b)
22 {
23     return a.sum>b.sum;
24 }
25 int main()
26 {
27     freopen("zyougamaya.in","r",stdin);
28     freopen("zyougamaya.out","w",stdout);
29     cin>>n;
30     for (int i=1;i<=n;i++)
31     {
32         ll u,v;
33         scanf("%I64d%I64d",&u,&v);
34         if (v>u) {
35             abled[++idi].fight=u;abled[idi].val=v-u;
36         }
37         else {
38             attack[++idj].fight=u;attack[idj].sum=v+u;
39         }
40     }
41     sort(abled+1,abled+1+idi,comp1);
42     sort(attack+1,attack+1+idj,comp2);
43     bool b=false;
44     for (int i=1;i<=idi;i++)
45     {
46         if (!b&&s+abled[i].val>=abled[idi].fight){
47             pos=abled[i].fight;    b=true;
48         }
49         s+=abled[i].val;//前缀和 
50     }
51     ll ans1=0,ans2=0;
52     for (int i=1;i<=idj;i++)
53     if (attack[i].fight>=pos){
54         ans1=s+attack[i].sum;
55         break;
56     }
57     ans2=s+abled[idi].fight*2;
58     printf("%I64d",max(ans1,ans2));
59     return 0;
60 }

第三题:

  有一个文件系统,支持7个操作:加入文件,加入文件夹,打开文件夹,删除文件,删除文件夹,回到上一个路径,输出当前路径的所有文件、文件夹。

解:

  一看就是个模拟。乱搞就可以了。注意细节。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define maxn 105
  6 using namespace std;
  7 int q,cur=1,idx=1,p;
  8 int tot,he[maxn],ne[maxn],to[maxn];
  9 struct pp{
 10     int typ,fa;
 11     bool zai;
 12     char na[maxn*2];
 13 };
 14 pp s[maxn];
 15 void add(int a,int b,int t)
 16 {
 17     tot++;to[tot]=b;ne[tot]=he[a];he[a]=tot;
 18     s[b].fa=a;s[b].typ=t;s[b].zai=true;
 19 }
 20 void work1()//返回父路径 
 21 {
 22     if (s[cur].fa) cur=s[cur].fa;
 23     else printf("No parent directory!
");
 24 }
 25 void work2(char x[])//进入 文件夹 
 26 {
 27     int len=strlen(x+1);
 28     for (int i=he[cur];i;i=ne[i])
 29     if (s[to[i]].typ==2&&s[to[i]].zai){//wen jian jia
 30         int l=strlen(s[to[i]].na+1);
 31         if (l!=len) continue;
 32         bool yes=false;
 33         for (int j=1;j<=len;j++)
 34             if (s[to[i]].na[j]!=x[j]) {yes=true;
 35                 break;
 36             }
 37         if (yes) continue;
 38         cur=to[i];
 39         return ;
 40     }
 41     printf("No such directory!
");
 42 }
 43 void work3(char x[],int t)//找文件(夹),创文件(夹) 
 44 {
 45     int len=strlen(x+1);bool have=false;
 46     for (int i=he[cur];i;i=ne[i])
 47     if (s[to[i]].typ==t&&s[to[i]].zai){
 48         int l=strlen(s[to[i]].na+1);
 49         if (l!=len) continue;
 50         bool yes=false;
 51         for (int j=1;j<=len;j++)
 52             if (s[to[i]].na[j]!=x[j]) {yes=true;
 53                 break;
 54             }
 55         if (yes) continue;
 56         have=true;
 57         break;
 58     }
 59     if (!have) {
 60         ++idx;
 61         add(cur,idx,t);
 62         for (int i=1;i<=len;i++)
 63           s[idx].na[i]=x[i];
 64     }
 65     else{
 66         if (t==1) printf("File already exists!
");
 67         else printf("Directory already exists!
");
 68     } 
 69 }
 70 void work4(char x[],int t)//删除文件或文件夹 
 71 {
 72     int len=strlen(x+1);bool have=false;
 73     for (int i=he[cur];i;i=ne[i])
 74     if (s[to[i]].typ==t&&s[to[i]].zai){
 75         int l=strlen(s[to[i]].na+1);
 76         if (l!=len) continue;
 77         bool yes=false;
 78         for (int j=1;j<=len;j++)
 79             if (s[to[i]].na[j]!=x[j]) {yes=true;
 80                 break;
 81             }
 82         if (yes) continue;
 83         have=true;
 84         s[to[i]].zai=false;
 85         return ;
 86     }
 87     if(t==1) printf("No such file!
");
 88     else printf("No such directory!
");
 89 } 
 90 void print(int x)
 91 {
 92     if (!s[x].zai) return ;
 93     if (s[x].typ==1){
 94         printf("%s ",s[x].na+1);
 95         cout<<"<F>"<<endl;
 96     }
 97     else {
 98         printf("%s ",s[x].na+1);
 99         cout<<"<D>"<<endl;
100     }
101 }
102 void work7(int pi)//ls 输出 递归 
103 {
104     int now=to[pi];
105     if (ne[pi]==0) {
106         print(now);
107         return ;    
108     }
109     work7(ne[pi]);
110     print(now);
111 }
112 int main()
113 {
114     freopen("nacumegu.in","r",stdin);
115     freopen("nacumegu.out","w",stdout);
116     cin>>q;
117     while (q)
118     {
119         char op[10],name[maxn*2];
120         scanf("%s",op);
121         if (op[0]=='l'){
122             p=he[cur];
123             work7(p);
124             q--;//***
125             continue;//***
126         }
127         scanf("%s",name+1);
128         if (op[0]=='c'){
129             if (name[1]=='.') 
130                 work1();
131             else 
132                 work2(name);
133         }
134         else if(op[0]=='t') work3(name,1);
135         else if (op[0]=='r'){
136             if (strlen(op)==2) 
137                 work4(name,1);
138             else 
139                 work4(name,2);
140         }
141         else if (op[0]=='m') work3(name,2);
142         q--;
143     }
144     return 0;
145 }
原文地址:https://www.cnblogs.com/lx0319/p/6044616.html