No, there is nothing wrong with using a backup for initial deployment, in fact I would say that this is often the safest way to do it. There isn't really any "contamination" that can happen unless you have hard-coded things like server names or database names that are different in production than in the test environment.
Though a backup / restore (much like your own DDL script restricted to the database) won't bring along things like server-level logins, linked servers, SQL Agent jobs, etc.
There are some other side benefits that you get with a backup that you don't necessarily get with a DDL script, for example if you created your original table like this:
CREATE TABLE dbo.foo
bar INT PRIMARY KEY,
mort INT FOREIGN KEY REFERENCES dbo.mort(MortID),
x TINYINT CHECK (x IN (1,2)),
y INT NOT NULL DEFAULT 1
All of these constraints have system-generated names, like
PK__foo__DE90ECFFA28BBAB8. When you run this same script in production, the name will be different, unless you scripted that exact table definition from the test environment. This can cause problems later if you generate drop/create/alter scripts from test and need to run them in production.
You will also get all of the data in lookup tables etc. when you take a backup, which you'll manually have to script in order to get that data onto production. (Though you have to be sure to clear out any test data that you don't want in production, too.)
And a weakness of scripting this out yourself is that you have to ensure all of the objects are created in the correct dependency order. You may have dependencies in place in test that are missing in production because the objects weren't generated in the correct order.
When it comes down to it, a backup is just cleaner. And you should be testing the database when it is deployed, so you should find any "contaminations" quite quickly, and correct them in both environments.
Once the database is initially deployed, obviously the only way to deploy changes at a later date is to script them. I've had great luck generating compare / deploy scripts using Red-Gate's SQL Compare. While Remus is absolutely right, that source control is the best solution to this, in reality source control is usually going to store a
CREATE TABLE script, which doesn't get you very far when you've added a column and changed another column's data type - you still need to build some kind of diff script that will apply only the changes to production, not drop and re-create the table.
If you have things like local lookup tables that are in other databases or could be in different servers, then instead of hard-coding those names in your code, you should use synonyms. Then you only have to ensure the synonyms are correct in each environment, rather than finding all the three/four part names in all of your modules and updating them upon deployment. And if you have local file paths that differ between environments, use a central properties table instead of hard-coding those paths into your procedures etc.
In theory you could use a backup and restore methodology later but that does not work well if the production database is already in use - it gets kind of tricky to restore a database from test and not lose any of the data that has been collected in production.