【日常學習】【搜索遞推和其他】10.21.2015校內測試總結

哭瞎了···昨天夜裏寫了一半多的博客因爲卡機就這麼沒了TUT今天重新寫,浪費我多少時間TUT

第一題 RQNOJ358 線段

畫個圖就知道是兩點間距離的二倍···(我太傻竟沒看出來)

但是!這是小圓圓心在大圓外的情況,如果在大圓內部,畫圖可知正解是大圓直徑

然而···出題人竟然沒發現這一點於是只用了第一種解法沒加特判···

所以說蠢萌的出題人···

代碼

標準解(OJAC)

//chord
//copyright by ametake
#include
#include
#include
#include
using namespace std;

int xa,ya,xb,yb,ra,rb;
double ans;

int main()
{
    freopen("chord.in","r",stdin);
	freopen("chord.out","w",stdout);	
    //freopen("1.txt","r",stdin);
	//freopen("2.txt","w",stdout);
    scanf("%d%d%d",&xa,&ya,&ra);
    scanf("%d%d%d",&xb,&yb,&rb);
    ans=sqrt((double)(xb-xa)*(double)(xb-xa)+(double)(yb-ya)*(double)(yb-ya));
    
    ans*=2;
    printf("%.6f\n",ans);
    return 0;
}
正解
//chord
//copyright by ametake
#include
#include
#include
#include
using namespace std;

int xa,ya,xb,yb,ra,rb;
double ans;

int main()
{
    freopen("chord.in","r",stdin);
	freopen("chord.out","w",stdout);	
    //freopen("1.txt","r",stdin);
	//freopen("2.txt","w",stdout);
    scanf("%d%d%d",&xa,&ya,&ra);
    scanf("%d%d%d",&xb,&yb,&rb);
    ans=sqrt((double)(xb-xa)*(double)(xb-xa)+(double)(yb-ya)*(double)(yb-ya));
    int r=max(ra,rb);
    if (ans<=r) ans=r;
    ans*=2;
    printf("%.6f\n",ans);
    return 0;
}

第二題 循環 NOIP2005PJ4
誰說PJ能AK的···
這是一個遞推題,要寫高精。
如果暴搜,乘冪上限到五百多能拿三十分···
但也只能三十分,因爲其他點答案都是十的幾十次方···
暴搜程序

(幸虧我點了保存可惡的CSDN寫到第二題又給我卡死了!!!可惡!!!)
(就在我說這句話後當我粘上代碼第三次卡死了)
//circle
//copyright by ametake
//思路 從基數開始一個個嘗試基數的倍數 第一次快速冪 之後高精乘即可 每次檢驗
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

const int sx=600; 
const int maxn=100+10;
//const int power=1;
const int base=10;
const int jishu[10]={1,1,4,4,2,1,1,4,4,2};

int a[maxn],ans[maxn],c[maxn];
char cc[maxn];
int now[maxn],jj[maxn];
int k;

void multi(int *aa,int *b)
{
    memset(c,0,sizeof(c));
    int len1=aa[0];
    int len2=b[0];
    c[0]=min(100,aa[0]+b[0]-1);
    for (int i=1;i<=len1;i++)
    {
        for (int j=1;j<=min(len2+i-1,100-i+1);j++)
        {
            c[i+j-1]+=aa[i]*b[j];
            c[i+j]+=c[i+j-1]/base;
            c[i+j-1]%=base;
        }
    }
    if (c[c[0]+1]) if (c[0]<100) c[0]++;
    memcpy(aa,c,sizeof(c));
}

bool check()
{
    memcpy(ans,now,sizeof(now));
    multi(ans,a);
    bool noo=false;
    for (int i=1;i<=k;i++) if (ans[i]!=a[i]) noo=true;
    if (noo) return false;
    else return true;
}

int main()
{
    //freopen("1.txt","r",stdin);
    //freopen("2.txt","w",stdout);
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout);
    scanf("%s",cc);
    scanf("%d",&k);
    int p=0;//p是基數,a是最原始數組,now是當前數組,由a求冪而來且指數一定爲基數的倍數,ans是檢驗時用的要再乘一遍a 
    now[0]=k;
    a[0]=k;
    if (k>strlen(cc))
    {
        printf("-1\n");
        return 0;
    }
    for (int i=strlen(cc);i>=1;i--)
    {
        a[++p]=cc[i-1]-'0';
        now[p]=cc[i-1]-'0';
        if (p==k) break;
    }
    p=jishu[now[1]];//從此a不動 
    if (p>1) multi(now,now);
    if (p==4) multi(now,now);
    memcpy(jj,now,sizeof(now));//jj是基底數組 每次乘它 
    if (check())
    {
        printf("%d\n",p);
        return 0;
    } 
    else
    {
        for (int i=2;i<=sx/p;i++)
        {
            multi(now,jj);
            if (check())
            {
                printf("%d\n",p*i);
                return 0;
            } 
        }
    }
    printf("-1\n");
    return 0;
}

這道題正解至今不明白爲什麼是十次,只是知道每次對於某一位向前遞推最後求乘積···這個大家自己去網上搜吧

第三題 altitude
沒找到原題,反正也無所謂
直接暴力枚舉可過
//altitude
//copyright by ametake
#include
#include
#include
using namespace std;

const int maxn=100+10;
int a[maxn][maxn];
int n,s,k;

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

int main()
{
    //freopen("1.txt","r",stdin);
    //freopen("2.txt","w",stdout);
    freopen("altitude.in","r",stdin);
    freopen("altitude.out","w",stdout);
    n=read();
    s=read();
    k=read();
    int x,y;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            a[i][j]=read();
        }
    }
    for (int i=1;i<=k;i++)
    {
        x=read();
        y=read();
        int mi=0x3f3f3f;
        int ma=0;
        for (int i=x;i<=x+s-1;i++)
        {
            for (int j=y;j<=y+s-1;j++)
            {
                ma=max(a[i][j],ma);
                mi=min(a[i][j],mi);
            }
        }
        printf("%d\n",ma-mi);
    }
    return 0;
}
也可以用DP做,但時間複雜度更大,因爲DP球了所有的狀態
參見顯擺代碼 這裏不放了

第四題 sudoku
近似於codevs數獨挑戰 其實只是讀入方式變了而已
暴搜即可 一道典型的棋盤暴搜題 和八皇后一樣的判斷 其實可以參見靶形數獨 我感覺我幾乎是比着黃學長靶形數獨寫的

//sudoku
//copyright by ametake
#include
#include
#include
#define dfsnext(x,y) {y==9?dfs(x+1,1):dfs(x,y+1);}
using namespace std;

int a[10][10];//ËÑË÷Êý×é 
bool b[10][10];//ÊÇ·ñÓÐԭʼÊý×Ö ÓÐÊÇtrue true²»ÄÜÌîÊý 
bool h[10][10],l[10][10],lit[10][10];//true²»ÄÜÌî 
bool ok=false;

bool can(int x,int y,int num)
{
    if (h[x][num]) return false;
    if (l[y][num]) return false;
    if (lit[(x-1)/3*3+(y-1)/3+1][num]) return false;
    h[x][num]=true;
    l[y][num]=true;
    lit[(x-1)/3*3+(y-1)/3+1][num]=true;
    a[x][y]=num;
    return true;
}

void del(int x,int y,int num)
{
    h[x][num]=l[y][num]=lit[(x-1)/3*3+(y-1)/3+1][num]=false;
    a[x][y]=0;
}

void print()
{
    for (int i=1;i<=9;i++)
    {
        for (int j=1;j<=9;j++)
        {
            printf("%d",a[i][j]);
        }
        printf("\n");
    }
}

void dfs(int x,int y)
{
     if (ok) return;
     if (x==10&&y==1)
     {
         ok=true;
         print();
         return;
     }
     if (b[x][y]) dfsnext(x,y);
     if (!b[x][y])
     {
         for (int i=1;i<=9;i++)
         {
             if (can(x,y,i))
             {
                dfsnext(x,y);
                if (ok) break;
               del(x,y,i);
             }
         }
     }
}

int main()
{
    freopen("sudoku.in","r",stdin);
    freopen("sudoku.out","w",stdout);
    char s[10];
    for (int i=1;i<=9;i++)
    {
        scanf("%s",s);
        for (int j=1;j<=9;j++)
        {
            if (s[j-1]=='?') a[i][j]=0;
            else
            {
                a[i][j]=s[j-1]-'0';
                h[i][s[j-1]-'0']=true;
                l[j][s[j-1]-'0']=true;
                lit[(i-1)/3*3+(j-1)/3+1][s[j-1]-'0']=true;
                b[i][j]=true;
            }
        } 
    }
    dfs(1,1);
    return 0;
}


總結:思維能力和代碼實現能力仍需增強 基礎部分尤其是深廣搜還要再練 算法還應該更紮實 加油啊

——連重陽節都過去了
——霧霾天,外面灰濛濛的一片,好像要下雨一樣
——江涵秋影雁初飛,與客攜壺上翠微

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章