1. 程式人生 > >UVA-1588 紫書習題3-11換抵擋裝置

UVA-1588 紫書習題3-11換抵擋裝置

大致題意:給你連個長度分別為n1,n2且每列高度只為1或2的長條,然後將他們拼在一起,高度不能超過3,問他們拼在一起的最短長度。

 

 Sample Input

2112112112

2212112

12121212

21212121

2211221122

21212

Sample Output

10

8

15

本體思路: 

剛開始我的思路是先讓短的在下面,讓上面的不動,通過移動下面的長條來逐一比較,當長條從左到右移動完了之後,就能找到最短。但是程式碼交上去之後 樣例能通過但是一直WA,可能較複雜的資料過不了。(錯誤的思路)

後來看了一下網上的題解,也是通過移動下面的來進行比較,不同的是,它是讓兩個長條都從第一個元素開始比較,從左到右移動下面的長條。比較完之後,再將上下長條顛倒位置,再比較一遍,這樣就將全部的情況都比較完了。他的這種程式碼書寫很簡單,很值得我借鑑。(正確的思路) 

我的程式碼:(錯誤的)

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    char a[105],b[105];
    int a1[205],b1[205];
    while(~scanf("%s%s",a,b))
    {
        int len1=strlen(a);
        int len2=strlen(b);
        if(len1<len2)
        {
            for(int i=0;i<len2;i++)
                a1[i]=b[i]-'0';
            for(int i=0;i<len2;i++)
                b1[i]=a[i]-'0';
            swap(len1,len2);
        }
        else
        {
            for(int i=0;i<len1;i++)
                a1[i]=a[i]-'0';
            for(int i=0;i<len2;i++)
                b1[i]=b[i]-'0';
        }
        int flag;
        int sum,ans=len1+len2;
        for(int j=len2-1;j>=0;j--)
        {
            flag=1;///更新資料
            for(int k=0;k<len2-j&&j+k<len2;k++)
            {
                if(a1[k]==2&&b1[j+k]==2)
				{flag=0;break;}
            }
            if(flag==0) continue;
            else {/*cout<<"flag="<<flag<<"  "<<j<<endl;*/sum=len1+j;}
            if(sum<ans)
                ans=sum;
        }
		int win;int i,j;
		for(i=0;i<len1;i++)
		{
			win=1;///更新資料
			for(j=0;j<len2&&i+j<len1;j++)
			{
				if(a1[i+j]==2&&b1[j]==2)
				{win=0;break;}
			}
			if(win==0) continue;
			else {/*cout<<"win="<<win<<endl;*/sum=len1;}
			if(sum<ans)
				ans=sum;
		}
		cout<<ans<<endl;
		//cout<<i<<"  "<<j<<endl;

    }
    return 0;
}

借鑑的程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    char a[105],b[105];
    int aa[205],bb[205];///陣列要開足夠大  陣列空間不夠時也會WA
    while(~scanf("%s%s",a,b))
    {
        int lena=strlen(a);
        int lenb=strlen(b);
        memset(aa,0,sizeof(aa));
        memset(bb,0,sizeof(bb));
        int ans1,ans2,ans;
        int i,j;
        for(i=0;i<lena;i++)///將字元轉化為對應的數字
            aa[i]=a[i]-'0';
        for(i=0;i<lenb;i++)
            bb[i]=b[i]-'0';
        for(i=0;i<lena;i++)///先讓a串在上面b串在下面,通過移動b串來比較
        {
            for(j=0;j<lenb;j++)
            {
                if(aa[i+j]+bb[j]>3)
                    break;
            }
            if(j==lenb)////說明都比較一遍之後串a和串b都相等 比較完了之後j==lenb
                break;
        }
        if(i+lenb>lena) ans1=i+lenb;
        else  ans1=lena;
        ///程式碼和上面的相似
        for(i=0;i<lenb;i++)///然後顛倒位置,讓b串在上面a串在下面,通過移動a串來比較
        {
            for(j=0;j<lena;j++)
            {
                if(bb[i+j]+aa[j]>3)
                    break;
            }
            if(j==lena)  break;
        }
        if(i+lena>lenb)  ans2=i+lena;
        else   ans2=lenb;
        ans=min(ans1,ans2);
        printf("%d\n",ans);///最終選取兩種方式中較小的;
    }
    return 0;
}

知識點:

1、將字串轉化為數字時,我開的陣列太小了  導致一開始一直WA不知道為什麼。下次要注意陣列是否夠大。將數字在字元轉化為數字時,用a[i]-'0';

2、用flag,win做標記時,注意放在的位置,為了更新資料。本題應注意是將flag=1放在for的裡面還是要放在外面。一開始我的程式碼就因為放錯位置了導致找了半天錯誤才找到。很重要的一個知識點,要記得長記性。

3、可以通過輸出中間資料來檢查程式碼出現的問題。

4、不要用長得很像的識別符號!例如,a,a1,最好不要用。以後設定識別符號時要見名知其意!