POJ 1780 Code

Code
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2259   Accepted: 820

Description

KEY Inc., the leading company in security hardware, has developed a new kind of safe. To unlock it, you don't need a key but you are required to enter the correct n-digit code on a keypad (as if this were something new!). There are several models available, from toy safes for children (with a 2-digit code) to the military version (with a 6-digit code). 

The safe will open as soon as the last digit of the correct code is entered. There is no "enter" key. When you enter more than n digits, only the last n digits are significant. For example (in the 4-digit version), if the correct code is 4567, and you plan to enter the digit sequence 1234567890, the door will open as soon as you press the 7 key. 

The software to create this effect is rather simple. In the n-digit version the safe is always in one of 10n-1 internal states. The current state of the safe simply represents the last n-1 digits that have been entered. One of these states (in the example above, state 456) is marked as the unlocked state. If the safe is in the unlocked state and then the right key (in the example above, 7) is pressed, the door opens. Otherwise the safe shifts to the corresponding new state. For example, if the safe is in state 456 and then you press 8, the safe goes into state 568. 

A trivial strategy to open the safe is to enter all possible codes one after the other. In the worst case, however, this will require n * 10n keystrokes. By choosing a good digit sequence it is possible to open the safe in at most 10n + n - 1 keystrokes. All you have to do is to find a digit sequence that contains all n-digit sequences exactly once. KEY Inc. claims that for the military version (n=6) the fastest computers available today would need billions of years to find such a sequence - but apparently they don't know what some programmers are capable of...

Input

The input contains several test cases. Every test case is specified by an integer n. You may assume that 1<=n<=6. The last test case is followed by a zero.

Output

For each test case specified by n output a line containing a sequence of 10n + n - 1 digits that contains each n-digit sequence exactly once.

Sample Input

1
2
0

Sample Output

0123456789
00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990

Source

Ulm Local 2004


呃其實剛做這個題是20多天前了。。當時就不會 現在終於會了 竟然是圖論的題

題目大意是:

你需要輸入n位的密碼 如果前n-1位對了 第n位也對的話 就打開了

否則此時的後n-1位變成了前n-1位 等待最後一位的輸入 依次下去 題目要求給出按鍵的順序 使得字典序最小

相當於給出一串數組序列 有一個長度爲n的窗戶 從1-n開始 每次後移一個格

如樣例

2

00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990
依次是00 01 10 02 20 03 30 04 ... 80 09 91 11 12 21 13 .... 90

如果從n個0 到n個9 一個一個試的話 最壞情況是n*10^n次

給出的答案長度是10^n+n-1 如果每一次的數字都不重複的話 而且兩個數之間共享了n-1位相同的數字

窗口每向後滑一次 產生一個新的數 一共10^n個數 滑了10^n-1次 加上第一個數的長度n 所以答案一共10^n+n-1個數字

而所有數字要求出現且僅出現1次

把每個數字轉化爲邊 每個數前n-1位到後n-1位之間有一條邊 求圖的歐拉回路

而且還要用非遞歸寫。。第一次寫模擬遞歸用的goto

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

struct self
{
    int x,y,nxt;
}s[3000001];
int fst[100001];
int flag[3000001];
int ret[3000001];
int ans;
int m,n,x,y;
int lim;

void calc(int k)
{
    lim=1;
    k--;
    n=0;
    memset(flag,0,sizeof(flag));
    memset(fst,-1,sizeof(fst));
    ans=0;
    while(k)
    {
        k--;
        lim*=10;
    }
}
void add(int x,int y)
{
    n++;
    s[n].x=x;
    s[n].y=y;
    s[n].nxt=fst[x];
    fst[x]=n;
}

struct node
{
    int u,e;
}st[3000001];
int top;

void dfs()
{
    top=1;
    st[1].u=0;
    st[1].e=-1;
    a:
    while(top)
    {
        node u=st[top];
        for(int e=fst[u.u];e!=-1;e=s[e].nxt)
        {
            if(!flag[e])
            {
                flag[e]=1;
                top++;
                st[top].u=s[e].y;
                st[top].e=e;
                goto a;
            }
        }
        top--;
        ans++;
        ret[ans]=u.e;
    }
}
inline void out(int x)
{
    if(x>9)
        out(x/10);
    putchar(x%10+'0');
}
int main()
{
    //freopen("1.out","w",stdout);
    while(scanf("%d",&m)==1 && m)
    {
        if(m==1)
        {
            printf("0123456789\n");
            continue;
        }
        calc(m);
        int tt=lim/10;
        for(int i=0;i<lim;i++)
            for(int j=9;j>=0;j--)
            {
                x=i;
                y=x%tt*10+j;
                add(x,y);
            }
            
        dfs();
        /*
        for(int i=1;i<m;i++)printf("0");
        for(int i=ans-1;i>=1;i--)
            printf("%d",s[ret[i]].y%10);
        printf("\n");
        */
        for(int i=1;i<m;i++)out(0);
        for(int i=ans-1;i>=1;i--)
            out(s[ret[i]].y%10);
        printf("\n");
    }
    return 0;
}

不用輸出外掛



加上輸出外掛 G++竟然比C++還快



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