Other——關於1月21日測試的分析總結

TEXT 1:Telephone 点击打开链接

本題主要考查了簡單的字符串處理,當然也可以用hash+排序來解决。我最初考慮到用hash來儲存數據,但想到此題數據較小,且字串長度及字符串的變化比較簡單,沒必要用hash大動干戈(當然,也怕自己寫錯),就直接採用sort排序+兩for迴圈暴力解决問題。

不過也由此發現自己關於hash方面程式碼能力還有所欠缺。一遇到一些字串處理的題就首選暴力。雖然有時候可以僥倖AC,但hash的作用不容小覷,自己需要對hash再加鞏固。

  以下是自己的暴力代碼:

  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstdlib>  
  4. #include<algorithm>  
  5. #include<cmath>  
  6. #include<cstring>  
  7. #include<string>  
  8. using namespace std;  
  9. struct node{  
  10.     int zhi,cfcs;  
  11. }same[200020];  
  12. int n,len,tot,all;  
  13. char s[17];  
  14. int num[100010];  
  15. int alpha[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9,0};  
  16. int main()  
  17. {  
  18.     freopen("telephone.in","r",stdin);  
  19.     freopen("telephone.out","w",stdout);  
  20.     ios::sync_with_stdio(false);  
  21.     cin.tie(NULL);  
  22.     scanf("%d\n",&n);  
  23.     int m=n;  
  24.     memset(same,0,sizeof(same));  
  25.     while(n--)  
  26.     {  
  27.         gets(s);  
  28.         len=strlen(s);  
  29.         tot=1;  
  30.         for(int i=0;i<len;i++)  
  31.         {  
  32.             if(s[i]!='-')  
  33.             {  
  34.                 int x;  
  35.                 if((s[i]-48)>=0&&(s[i]-48)<=9) x=(s[i]-48);  
  36.                 else x=alpha[s[i]-65];  
  37.                 for(int j=tot;j<7;j++)  
  38.                     x*=10;  
  39.                 num[n]+=x;  
  40.                 tot++;  
  41.             }  
  42.         }  
  43.     }  
  44.     sort(num,num+m);  
  45.     all=1;  
  46.     for(int i=0;i<m;i++)  
  47.     {  
  48.         if(num[i]==num[i+1])  
  49.         {  
  50.             if(same[all-1].zhi!=num[i])  
  51.             {  
  52.                 same[all].zhi=num[i];  
  53.                 same[all].cfcs++;  
  54.                 all++;  
  55.             }  
  56.             else  
  57.                 same[all-1].cfcs++;  
  58.         }  
  59.     }  
  60.     if(all>1)  
  61.     {  
  62.         for(int i=1;i<all;i++)  
  63.         {  
  64.             char ch[10];  
  65.             sprintf(ch,"%d",same[i].zhi);  
  66.             for(int j=0;j<=2;j++) cout<<ch[j];  
  67.             cout<<"-";  
  68.             for(int j=3;j<=6;j++) cout<<ch[j];  
  69.             cout<<" "<<same[i].cfcs+1<<endl;  
  70.         }  
  71.     }  
  72.     else printf("No duplicates.\n");  
  73.     return 0;  

TEST 2: 數對個數 点击打开链接

本題限制了空間大小,然而我並不會算。。。

所以最開始定義數組的時候便定義太大了:

int tot[10000000][2];
但後來發現,改成如下在OJ上就AC了:

int tot[1000000][2];
不過這也反映了我在一些基本問題(如計算空間、計算時間複雜度。。。)上的問題。雖然問題都體現在代碼的細節上,但是在NOIP甚至是NOI上都是非常致命的錯誤。

另外,解决此題可以採用很多方法,比如樸素算灋、二分、隊列等。我採用了隊列,先將數據排序,然後枚舉每個數位,將重複的數記錄下來,以及隊列中出現的數用tot[1000000][1]標記;然後進行第二次迴圈查找,
並且有num[tot[ab[i]][1]]做相同數位的標記,所以實際for迴圈的次數遠遠小於所有的數位總數。

而此題還可以用二分解决,用二分來查找a-b=c中的b。我最初也想過用二分甚至hash來查找b,但最後還是採用了數組num、tot[1000000][2]和一個變數all來判斷和查找,雖然在速度上比二分查找快很多,但是對於空間的利用是很低的,囙此容易超容。

這是我自己寫的:

用二分查找: 


所以顯而易見,二分在空間上還是占了優勢。
但是也反映了我在空間計算上還有些不足,而對於暴力和先進算灋之間的選擇上,則最好要發揮解决關鍵問題上各自的優勢。
總代碼如下:

  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstdlib>  
  4. #include<algorithm>  
  5. #include<cmath>  
  6. #include<cstring>  
  7. #include<string>  
  8. using namespace std;  
  9. int num[200020];  
  10. int n,c,all;  
  11. int ab[200020];  
  12. int tot[1000000][2];  
  13. long long ans=0;  
  14. int main()  
  15. {  
  16.     freopen("dec.in","r",stdin);  
  17.     freopen("dec.out","w",stdout);  
  18.     memset(num,0,sizeof(num));  
  19.     ios::sync_with_stdio(false);  
  20.     cin.tie(NULL);  
  21.     cin>>n>>c;  
  22.     for(int i=1;i<=n;i++) cin>>ab[i];  
  23.     sort(ab+1,ab+1+n);  
  24.     all=1;  
  25.     for(int i=1;i<=n;i++)  
  26.     {  
  27.         if(tot[ab[i]][0]==0)tot[ab[i]][0]=1;  
  28.         if(ab[i]==ab[i+1])  
  29.         {  
  30.             if(tot[ab[i]][0]!=2)  
  31.             {  
  32.                 tot[ab[i]][0]=2;  
  33.                 tot[ab[i]][1]=all;  
  34.                 num[all]++;  
  35.                 all++;  
  36.             }  
  37.             else    num[all-1]++;  
  38.         }  
  39.     }  
  40.     for(int i=1;i<=n;i++)  
  41.     {  
  42.         int aa=1,bb=1;  
  43.         if(tot[c+ab[i]][0]>0)  
  44.         {  
  45.             if(tot[ab[i]][0]==2) aa+=num[tot[ab[i]][1]];  
  46.             if(tot[ab[i]+c][0]==2) bb+=num[tot[ab[i]+c][1]];  
  47.             ans+=aa*bb;  
  48.         }  
  49.         i+=num[tot[ab[i]][1]];  
  50.     }  
  51.     cout<<ans<<endl;  
  52.     return 0;  
  53. }  

TEST 3:分配教室 点击打开链接

最初想這道題的時候想法與ly的類似,但是我是將同樣一類的人合併再遞推的,所以出現了一些WA。當時有一點蒙,再加上不想改程式碼了,於是强加了一個不可靠的暴力,最初的代碼如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
int n,m;
int peo[2600];
int head1,head2;
int jia=0,yi=0,ans=1;
int samea[2501],sameb[2501];
int search(int x,int y,int jia,int yi)
{
	int yj=jia;
	int yy=yi;
	if(abs(jia-yi)<=m||jia==0||yi==0) return 1;
	else
	{
		int j=x;
		for(int i=y;i>=1;i--)
		{
			if(j>=1)
			{
				jia-=samea[i];
				yi-=sameb[j];
				if(abs(jia-yi)<=m||jia==0||yi==0)
				{
					ans+=search(x-j,y-i,yj-jia,yy-yi);
					return ans;
				}
				j--;
			}
		}
		return ans;
	}
}
int main()
{
	freopen("orz.in","r",stdin);
	freopen("orz.out","w",stdout);
	memset(samea,0,sizeof(samea));
	memset(sameb,0,sizeof(sameb));
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>peo[i];
	ans=1;
	head1=1;
	head2=1;
	for(int i=1;i<n;i++)
	{
		if(peo[i]==1)
		{
			if(peo[i]==peo[1+i])
				samea[head1]++,jia++;
			else
			{
				samea[head1]++;
				jia++;
				head1++;
			}
		}
		else
		{
			if(peo[i]==peo[i+1])
				sameb[head2]++,yi++;
			else
			{
				sameb[head2]++;
				yi++;
				head2++;
			}
		}
	}
	if(peo[n]==1) jia++;
	else yi++;
	int yj=jia,yy=yi;
	cout<<min(head1+head2-2,search(head2,head1,jia,yi))<<endl;
	return 0;
}

試後參照ly的想法自己寫了一遍,然後發現有三個WA:


代碼:

#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0;
int peo[2600];
int jia=0,yi=0;
void classroom(int jia,int yi,int wrx,int hfz)
{
	if(abs(jia-yi)<=m||jia==0||yi==0) ans++;
	else
	{
		int wmx=jia,wxy=yi;
		for(int i=wrx;i>=hfz;i--)
		{
			if(peo[i]==1) jia--;
			else yi--;
			if(abs(jia-yi)<=m||jia==0||yi==0)
			{
				ans++;
				classroom(wmx-jia,wxy-yi,wrx,i+1);
				break;
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>peo[i];
		if(peo[i]==1) jia++;
		else yi++;
	}
	classroom(jia,yi,n,1);
	cout<<ans<<endl;
	return 0;
}


這也說明了通過簡單的逆向推理是有缺陷的。所以DP終究還是有DP的道理,處理問題的時候不能只追求些程式碼一時的輕鬆,問題一定是要考慮全面的,不能僅僅通過自己簡簡單單的猜想而且不加驗證就開始程式設計。算灋雖然在思考時燒腦,但解决問題一定要抱著考慮問題全面的心態。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值